精华内容
下载资源
问答
  • Linux编写守护进程获取进程信息

    千次阅读 2019-04-07 15:46:14
    记录系统运行期间所有运行的进程,记录信息包括:进程PID,可执行程序名称,用户名,创建时间,撤销时间,开机能自启动

    目的

     记录系统运行期间所有运行的进程,记录信息包括:进程PID,可执行程序名称,用户名,创建时间,撤销时间,开机能自启动

    守护进程

    进程

    • 每个进程都有一个父进程
    • 当子进程终止时,父进程会得到通知并能取得子进程的退出状态。

    进程组

    • 每个进程也属于一个进程组
    • 每个进程主都有一个进程组号,该号等于该进程组组长的PID号
    • 一个进程只能为它自己或子进程设置进程组ID号

    会话期

    • 对话期(session)是一个或多个进程组的集合。
    • setsid()函数可以建立一个对话期:
    • 如果,调用setsid的进程不是一个进程组的组长,此函数创建一个新的会话期。
        (1)此进程变成该对话期的首进程
        (2)此进程变成一个新进程组的组长进程。
        (3)此进程没有控制终端,如果在调用setsid前,该进程有控制终端,那么与该终端的联系被解除。如果该进程是一个进程组的组长,此函数返回错误。
        (4)为了保证这一点,我们先调用fork()然后exit(),此时只有子进程在运行,
      子进程继承了父进程的进程组ID,但是进程PID却是新分配的,所以不可能是新会话的进程组的PID。从而保证了这一点。
    if((pid=fork())>0)  //parent
        exit(0);
    else if(pid==0){        //th1 child
        setsid();           //th1是成为会话期组长
        if(fork() ==0){     //th2不会是会话期组长(变成孤儿进程组)
            ...
        }
    }
    

    守护进程及其特性

    • 守护进程最重要的特性是后台运行。在这一点上DOS下的常驻内存程序TSR与之相似。
    • 其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。
    • 最后,守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,
      可以由作业规划进程crond启动,还可以由用户终端(通常是 shell)执行。
    • 总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。
      因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。

    守护进程的编程要点 (来自UEAP)

      前面讲过,不同Unix环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则其实都一样,区别在于具体的实现细节不同。这个原则就是要满足守护进程的特性。同时,Linux是基于Syetem V的SVR4并遵循Posix标准,实现起来与BSD4相比更方便。编程要点如下;

    • 在后台运行。
        为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。
        if(pid=fork())
            exit(0); //是父进程,结束父进程,子进程继续
    
    • 脱离控制终端,登录会话和进程组
        进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长:
    setsid();
    

    说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长 setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。

    • 禁止进程重新打开控制终端
        现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。
      可以通过使进程不再成为会话组长来禁止进程重新打开控制终端:
    if(pid=fork())
         exit(0); //结束第一子进程,第二子进程继续(第二子进程不再是会话组长)
    
    
    • 关闭打开的文件描述符
        进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们:
    for(i = 0;i<NOFILE;i++)           //关闭打开的文件描述符
            close(i);
    
    • 改变当前工作目录
        进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如 /tmp
    chdir("/")
    
    • 重设文件创建掩模
        进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除。
    umask(0);
    
    • 处理SIGCHLD信号
        处理SIGCHLD信号并不是必须的。 但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN
    signal(SIGCHLD,SIG_IGN);
    

    这样,内核在子进程结束时不会产生僵尸进程。 这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。

    实例

    编写创建守护进程的函数

    (博主将文件放在init.c文件中

    #include<unistd.h>
    #include<signal.h>
    #include<stdio.h>
    #include<sys/param.h>
    #include<sys/stat.h>
    #include <stdlib.h>
    
    void init_daemon()
    {
        int pid;
        int i;
        if (pid = fork())
            exit(0);           //结束父进程
        else if (pid < 0)
            exit(1);           //fork失败,退出
        //第一个子进程,后台继续执行
        setsid();              //第一个子进程成为新的会话组长和进程组长并与控制终端分离
        if(pid = fork())
            exit(0);            //结束第一个子进程
        else if(pid < 0)
            exit(1);            //fork失败,退出
        //第二个子进程,继续,此进程不再是回话组长
        for(i = 0;i<NOFILE;i++)           //关闭打开的文件描述符
            close(i);
    
        chdir("/");          //改变工作目录到/
        umask(0);               //重设文件创建掩模
        return ;
    }
    

    通过处理ps命令获取进程的信息

    (此文件在pid.c文件中

    
    
    
    #define _XOPEN_SOURCE 700          //解决strptime函数不能用的问题
    
    
    #include <stdlib.h>
    #include<stdio.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <dirent.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <stdlib.h>
    #include<time.h>
    #include<sys/types.h>
    #include<string.h>
    
    
    
    #define BUFF_LEN   1024    //行缓冲区的长度
    
    
    typedef struct{
    	pid_t pid;         //进程的pid
    	char user[20];     //进程用户名
    	char name[256];    //进程名称
    	char stime[50];    //开始时间
    	char etime[50];  //撤销时间
    }proc_info_st;
    
    void init_daemon(); //守护进程初始化函数
    void get_endTime(char *stime,char *etime,char *string);  //时间转换
    
    
    int main(int argc, char *argv[])
    {
        init_daemon();  //初始化为Daemon,守护进程的创建
        while(1){     
            FILE *fo;
            fo = fopen("/tmp/test.log","w");  //初始化输出文件
            fclose(fo);
    
            FILE *fp;
            char buffer[BUFF_LEN];            //存储文件信息
    
            fp = popen("ps -eo  pid,user,comm,etime,lstart","r");   //读取信息
            int i=0;
            while(fgets(buffer,sizeof(buffer),fp)){
                if(i == 0){           //第一行为标题,舍弃
                    i++;
                    continue; 
                }
                proc_info_st info;
                char e[50];          //存储进程运行时间
                sscanf(buffer,"%d\t%s\t%s\t%s\t%[^\n]",
                    &info.pid,info.user,info.name,e,info.stime);
                get_endTime(info.stime,e,info.etime);    //将运行时间和开始时间相加,得到结束时间
                if((fo = fopen("/tmp/test.log","a")) >= 0){   //输出到test.log文件中
                    fprintf(fo, "pid:%d\nuser:%s\nname:%s\nstart_time:%s\nend_time:%s\nrun_time:%s\n\n\n",
                        info.pid,info.user,info.name,info.stime,info.etime,e);  
                    fclose(fo);
                }
            }
            fclose(fp);
            sleep(60);    //每隔1min,保存一下信息
        }
    
    	
        return 0;
    }
    
    
    void get_endTime(char *stime,char *etime,char *string)
    {
    	struct tm s,e;
    	memset(&s, 0, sizeof(s));
    	memset(&e, 0, sizeof(e));
        strptime(stime, "%a\t%b\t%d\t%H:%M:%S\t%Y", &s);
        time_t ee = 0;
        if(strlen(etime) > 6) {
        	strptime(etime, "%H:%M:%S", &e);
        	ee+=e.tm_hour * 3600 + e.tm_min * 60 + e.tm_sec;
        }
        else{
        	strptime(etime, "%M:%S", &e);
        	ee+=e.tm_min * 60 + e.tm_sec;
        }
        time_t ss = mktime(&s);
        time_t all = ss + ee + 8 * 3600;
        struct tm *a;
        a = gmtime(&all);
        strftime(string, 50, "%a\t%b\t%d\t%H:%M:%S\t%Y",a);  
    }
    

    通过命令行编译文件

    gcc -g -o pid init.c pid.c   
    ./pid
    

    查看/tmp下,test.log文件是否有输出

    若成功,结果如下
    在这里插入图片描述

    设置开机自启动

    Ubuntu18.04 不再使用initd管理系统,改用systemd.

    然而systemd很难用,改变太大,跟之前的完全不同。

    使用systemd设置开机启动
    为了像以前一样,在/etc/rc.local中设置开机启动程序,需要以下几步:

    1. /lib/systemd/system/rc-local.service 链接到 /etc/systemd/system/ 目录下面来:
    sudo ln -fs /lib/systemd/system/rc-local.service /etc/systemd/system/rc-local.service
    
    1. 创建/etc/rc.local文件
    sudo touch /etc/rc.local 
    
    1. 赋可执行权限
    sudo chmod 755 /etc/rc.local 
    
    1. 编辑rc.local,添加需要开机启动的任务
    sudo gedit /etc/rc.local
    

    (我将编译好的pid文件放在了/usr下面,根据你的目录文件设置即可
    在这里插入图片描述
    5. 重启,完成。

    展开全文
  • Qt编写守护进程

    2019-03-02 14:56:06
    本篇文章提供一个软件实现守护进程的办法,原理就是udp通信,单独写个守护进程程序,专门负责检测主程序是否存在,不存在则启动。主程序只需要启动live类监听端口,收到hello就回复ok就行。 为了使得兼容任意程序,...
  • Linux编写守护进程

    2019-04-12 17:27:28
    Linux系统下编写一个守护进程,该守护进程能够记录系统运行期间所有运行的进程。记录信息包括:进程PID,可执行程序名称,用户名,创建时间等。 二、守护进程 1.概念 2.编写 三、实现 1.对于守护进程的...

    目录

     

    一、要求

    二、守护进程

    1.概念

    ​​​

     2.编写

    三、实现

    四、源码

     


    一、要求

    在Linux系统下编写一个守护进程,该守护进程能够记录系统运行期间所有运行的进程。记录信息包括:进程PID,可执行程序名称,用户名,创建时间等。

    二、守护进程

    1.概念

     2.编写

    三、实现

    1.对于守护进程的编写,按照上述步骤即可以写出,不会太难。

    2.要实现进程信息的记录,在终端中我们知道可以使用ps命令来查看进程信息,所以不妨考虑在C程序中执行shell命令来完成进程信息记录,正好可以使用system函数来执行shell命令。

    3.但执行shell命令如何把终端中的输出信息给保存到文件中呢?于是又想到了重定向可以实现此功能,比如ps -aux >> log.txt命令就可以将进程信息保存到当前目录的log.txt文件中,会自动创建该文件

    四、源码

    注意:对于chdir()函数和system函数的说明:如果system函数中执行的shell命令重定向的位置没有使用绝对路径,则chdir中的路径最好是绝对路径,不然重定向可能会出错,因为可能找不到路径。

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/param.h>
    #include <sys/stat.h>
    #include <time.h>
    #include <syslog.h>
    #include <stdbool.h>
     static bool flag = true;
    int init_daemon(void) 
    { 
    	int pid; 
    	int i; 	
    	pid = fork();
    	//子进程pid为0
    	if(pid > 0) {
    		exit(0); //结束父进程,使得子进程成为后台进程
    	}
    	else if(pid < 0) { 
    		return -1;
    	}
    	//建立一个新的进程组,在这个新的进程组中,子进程成为这个进程组的首进程,以使该进程脱离所有终端
    	setsid(); 
    	//改变工作目录,使得进程不与任何文件系统联系,使用绝对路径,以免开机自启后找不到文件路径
    	chdir("/home/xinger/Documents/OS/守护进程/");
        //关闭所有从父进程继承的不再需要的文件描述符
    	for(i=0;i< NOFILE;close(i++));
    	//将文件当时创建屏蔽字设置为0
    	umask(0);	
    	return 0;
    }
     
    int main() 
    { 
    	//创建守护进程
    	init_daemon();
    	system("echo 进程信息 >> log");
    	while(flag) { 
    		system("date >> log");//记录每次向log文件写入进程信息的时间
    		system("ps -aux >> log");//写入进程信息
    		sleep(20);
    	} 	
        return 0;
    }

     

    展开全文
  • 1、什么是守护进程 守护进程是运行在后台的一种特殊进程,它独立于控制终端并且周期性地执行某种任务或循环等待处理某些事件的发生; 守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机才随之一起...
  • 主要介绍了使用Python编写Linux系统守护进程实例,本文先是讲解了什么是守护进程,然后给出了一个Python语言的简单实现,需要的朋友可以参考下
  • 如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件,下面这篇文章主要给大家介绍了关于利用C#编写Linux守护进程的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
  • 主要介绍了C语言编写Linux守护进程实例,本文讲解了守护进程及其特性、守护进程的编程要点、守护进程代码实例等内容,需要的朋友可以参考下
  • (2)通过编写一个完整的守护进程,使读者掌握守护进程编写和调试的方法,并且进一步熟悉如何编写多进程 程序。 2、基本原理与方法(原理、流程图) (1)multi_proc_wrong.c程序同时创建两个子进程,两个进...

    1、实验内容与目的
    (1)通过编写多进程程序,使读者熟练掌握 fork()、exec()、wait()和 waitpid()等函数的使用,进一步理解在 Linux中多进程编程的步骤。
    (2)通过编写一个完整的守护进程,使读者掌握守护进程编写和调试的方法,并且进一步熟悉如何编写多进程
    程序。
    2、基本原理与方法(原理、流程图)
    (1)multi_proc_wrong.c程序同时创建两个子进程,两个进程之间是存在竞争关系的,因此会产生有执行顺序不确定的结果。
    在这里插入图片描述
    multi_proc.c程序则是首先创建子进程1,之后再创建子进程2,如此以来可以有效避免两个进程之间的竞争关系,执行的顺序也固然不会产生变化。

    (2)守护进程是在后台运行不受终端控制的进程(如输入、输出等),一般的网络服务都是以守护进程的方式运行。
    该程序中守护进程产生一个子进程,该子进程暂停 10s,然后自动退出,并由守护进程收集子进程退出的消息。在这里,子进程和守护进程的退出消息都在系统日志文件中输出。从而能够让我们更加了解进程的运行过程。
    在这里插入图片描述
    3、实验结果
    (1)
    在这里插入图片描述
    在这里插入图片描述
    (2)查看系统日志文件
    在这里插入图片描述
    在这里插入图片描述
    守护进程daemon_proc一直都有在运行
    4、结果分析
    多进程并发执行必然会产生竞争资源的关系,导致在执行的顺序上可能会发生变化。先后创建进程或设置休眠时间可以有效避免进程之间的冲突,达到预想的执行效果。
    守护进程是运行在后台的不受终端的进程,一般用于输入或是输出,只有在终端关闭的时候才会结束运行。

    /* multi_proc_wrong.c */ 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <sys/types.h> 
    #include <unistd.h> 
    #include <sys/wait.h> 
    int main(void) 
    { 
     pid_t child1, child2, child; 
     /*创建两个子进程*/ 
     child1 = fork(); 
     child2 = fork(); 
     /*子进程 1 的出错处理*/ 
     if (child1 == -1) 
     { 
     printf("Child1 fork error\n"); 
     exit(1); 
     } 
     else if (child1 == 0) /*在子进程 1 中调用 execlp()函数*/
      { 
     printf("In child1: execute 'ls -l'\n"); 
     if (execlp("ls", "ls","-l", NULL)<0) 
     { 
     printf("Child1 execlp error\n"); 
     } 
     } 
     
     if (child2 == -1) /*子进程 2 的出错处理*/ 
     { 
     printf("Child2 fork error\n"); 
     exit(1); 
     } 
     else if( child2 == 0 ) /*在子进程 2 中使其暂停 5s*/ 
     { 
     printf("In child2: sleep for 5 seconds and then exit\n"); 
     sleep(5); 
     exit(0); 
     } 
     else /*在父进程中等待两个子进程的退出*/ 
     { 
     printf("In father process:\n"); 
     child = waitpid(child1, NULL, 0); /* 阻塞式等待 */ 
     if (child == child1) 
     { 
     printf("Get child1 exit code\n"); 
     } 
     else 
     { 
     printf("Error occured!\n"); 
     } 
     
     do 
     { 
     child =waitpid(child2, NULL, WNOHANG);/* 非阻塞式等待 */ 
     if (child == 0) 
     { 
     printf("The child2 process has not exited!\n"); 
     sleep(1); 
     } 
     } while (child == 0); 
     
     if (child == child2) 
     { 
     printf("Get child2 exit code\n"); 
     } 
     else
      { 
     printf("Error occured!\n"); 
     } 
     } 
     exit(0); 
    }
    
    /*multi_proc.c */ 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <sys/types.h> 
    #include <unistd.h> 
    #include <sys/wait.h> 
    int main(void) 
    { 
     pid_t child1, child2, child; 
     
     /*创建两个子进程*/ 
     child1 = fork(); 
     
     /*子进程 1 的出错处理*/ 
     if (child1 == -1) 
     { 
     printf("Child1 fork error\n"); 
     exit(1); 
     } 
     else if (child1 == 0) /*在子进程 1 中调用 execlp()函数*/ 
     { 
     printf("In child1: execute 'ls -l'\n"); 
     if (execlp("ls", "ls", "-l", NULL) < 0) 
     { 
     printf("Child1 execlp error\n"); 
     } 
     } 
     else /*在父进程中再创建进程 2,然后等待两个子进程的退出*/ 
     { 
     child2 = fork(); 
     if (child2 == -1) /*子进程 2 的出错处理*/ 
     { 
     printf("Child2 fork error\n"); 
     exit(1); 
     } 
     else if(child2 == 0) /*在子进程 2 中使其暂停 5s*/ 
     {
      printf("In child2: sleep for 5 seconds and then exit\n"); 
     sleep(5); 
     exit(0); 
     } 
     
     printf("In father process:\n"); 
     child = waitpid(child1, NULL, 0); /* 阻塞式等待 */ 
     if (child == child1) 
     { 
     printf("Get child1 exit code\n"); 
     } 
     else 
     { 
     printf("Error occured!\n"); 
     } 
     
     do 
     { 
     child = waitpid(child2, NULL, WNOHANG ); /* 非阻塞式等待 */ 
     if (child == 0) 
     { 
     printf("The child2 process has not exited!\n"); 
     sleep(1); 
     } 
     } while (child == 0); 
     
     if (child == child2) 
     { 
     printf("Get child2 exit code\n"); 
     } 
     else 
     { 
     printf("Error occured!\n"); 
     } 
     } 
     exit(0); 
    }
    
    /* daemon_proc.c */ 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <sys/types.h> 
    #include <unistd.h> 
    #include <sys/wait.h> 
    #include <syslog.h> 
    int main(void) 
    { 
     pid_t child1,child2; 
     int i; 
     
     /*创建子进程 1*/ 
     child1 = fork(); 
     if (child1 == 1) 
     { 
     perror("child1 fork"); 
     exit(1); 
     } 
     else if (child1 > 0) 
     { 
     exit(0); /* 父进程退出*/ 
     } 
     /*打开日志服务*/ 
     openlog("daemon_proc_info", LOG_PID, LOG_DAEMON); 
     
     /*以下几步是编写守护进程的常规步骤*/ 
     setsid(); 
     chdir("/"); 
     umask(0); 
     for(i = 0; i < getdtablesize(); i++) 
     { 
     close(i);
      } 
     
     /*创建子进程 2*/ 
     child2 = fork(); 
     if (child2 == 1) 
     { 
     perror("child2 fork"); 
     exit(1); 
     } 
     else if (child2 == 0) 
     { /* 进程 child2 */ 
     /*在日志中写入字符串*/ 
     syslog(LOG_INFO, " child2 will sleep for 10s "); /*查看系统日志文件:tail /var/log/syslog*/
     sleep(10); 
     syslog(LOG_INFO, " child2 is going to exit! "); 
     exit(0); 
     } 
     else 
     { /* 进程 child1*/ 
     waitpid(child2, NULL, 0); 
     syslog(LOG_INFO, " child1 noticed that child2 has exited "); 
     /*关闭日志服务*/ 
     closelog(); 
     while(1) 
     { 
     sleep(10); 
     } 
     } 
    }
    
    展开全文
  • 利用网上下载的这段代码,成功实现了守护进程,原来守护进程是很简单的事情。
  • 本文实例讲述了Python实现Linux守护进程编写方法,分享给大家供大家参考,相信对于大家的Python程序设计会起到一定的帮助作用。具体方法如下: 1. 调用fork()以便父进程可以退出,这样就将控制权归还给运行你...
  • 编写Linux守护进程.pdf

    2021-09-07 00:55:07
    编写Linux守护进程.pdf
  • 守护进程介绍:linux中的守护进程是一种特殊进程。它独立于控制终端并且周期性的执行某种任务或等待处理某些事件的发生。 linux中大多数服务器就是守护进程实现的。例如: internet服务器中inetd, Web服务器中的...

    守护进程介绍:

    linux中的守护进程是一种特殊进程。它独立于控制终端并且周期性的执行某种任务或等待处理某些事件的发生。
    linux中大多数服务器就是守护进程实现的。例如: internet服务器中inetd, Web服务器中的http。守护进程也完成一些系统任务如作业规划进程crond
    linux启动时会启动很多系统服务进程,这些进程没有控制终端,无法直接和用户交互。其他进程都是在用户登陆时启动,用户注销时退出,但系统服务进程不受用户的登录或注销改变影响,一直运行着。这种进程有一个名字叫守护进程(Daemon)。
    用 ps ajx命令可以查看系统中的进程。
    这里写图片描述
    TPGID 一栏是-1都是没有控制终端的进程,也就是守护进程。
    COMMAND一栏中用[]括起来的表示内核线程。没有空间代码,没有程序名和命令行。


    创建函数

    pit_t setsid(void);

    创建一个守护进程的6个步骤:

    1. 调用umask将文件模式创建屏蔽字设为0。
    2. 调用fork,父进程退出。(1)如果进程是由shell命令启动的,退出父进程,shell认为该进程已经结束。(2)保证子进程不是一个进程组组长。
    3. 调用setsid函数创建一个新的会话。(1)调用进程会成为新会话的首进程。(2)调用进程会成为进程组组长。(3)调用进程没有控制终端。
    4. 将当前目录改为工作目录。
    5. 关闭不需要的文件描述符。
    6. 忽略SIGCHLD信号。

    两次fork的作用
    第一次fork:这里第一次fork的作用就是让shell认为这条命令已经终止,不用挂在终端输入上;再一个是为了后面的setsid服务,因为调用setsid函数的进程不能是进程组组长(会报错Operation not permitted),如果不fork子进程,那么此时的父进程是进程组组长,无法调用setsid。所以到这里子进程便成为了一个新会话组的组长。

    第二次fork:第二次fork是为了避免后期进程误操作而再次打开终端。因为打开一个控制终端的前提条件是该进程必须为会话组组长,而我们通过第二次fork,确保了第二次fork出来的子进程不会是会话组组长。

    程序代码:
    这里写图片描述
    这里写图片描述
    这里写图片描述
    程序正确执行后:

    • 创建一个会话,当前进程成为会话首进程,会话ID就是当前进程ID。
    • 创建一个新的进程组,当前进程就是组长进程,进程组ID就是当前进程ID。
    • 如果当前进程有一个控制终端,则该进程失去控制终端,成为没有控制终端的进程。
      再次用命令ps ajx 查看进程发现多了几个守护进程。
      这里写图片描述
    展开全文
  • linux 守护进程编写

    2020-07-30 19:08:01
    守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待。处理某些发生的事件。守护进程是一种很有用的进程。
  • 最近公司项目需要,需要在我们的嵌入式linux设备中创建一个守护进程,用于保护系统中的主进程,防止某些不可预期的意外导致主进程异常结束后,系统完全宕机没有任何反应,破坏用户体验感。但是,查阅诸多资料之后...
  • Linux 守护进程

    2020-04-13 16:51:50
    粉丝不过W 守护进程概述 守护进程,一般为 Daemon进程,常在系统引导载入时启动,在系统关闭时终止。许多后台服务都是通过守护进程实现的 ... 编写守护进程要遵循一个特定的流程,创建一个简单...
  • #守护进程,每隔5秒守护一次 while true do res=`ps -ef | grep 8000 | grep -v grep | wc -l` #查询8000端口下的运行进程的数目,也可以把8000改成想要守护的进程名 if [ $res -eq 0 ] #如果进程数为0 -eq跟==...
  • Linux守护进程编写

    千次阅读 2019-04-12 00:09:38
    Linux守护进程编写 环境:VMware 15 + ubuntu 16 护进程的特点 后台服务程序,随系统启动而启动。 很多系统服务通过守护进程完成。 守护进程的名字往往以字母‘d’结尾 生存周期长。系统装入时...
  • 创建子进程,父进程退出 这是编写守护进程的第一步。由于守护进程是脱离控制终端的,因此,完成第一步后就会在Shell终端里造成一程序已经运行完毕的假象。之后的所有工作都在子进程中完成,而用户在Shell终端里则...
  • 编写Linux守护进程

    2010-10-08 14:03:32
    编写Linux守护进程
  • 守护进程(daemon)是指在UNIX或其他多任务操作系统中在后台执行的电脑程序,并不会接受电脑用户的直接操控。此类程序会被以进程的形式初始化。通常,守护进程没有任何存在的父进程(即PPID=1),且在UNIX系统进程...
  • linux守护进程

    千次阅读 2018-03-08 21:05:10
    1.守护进程最重要的特性是后台运行。 2.守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符...因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程(一个特殊...
  • Linux-守护进程工具(Supervisor)

    千次阅读 2020-04-16 13:41:01
    由于有许多程序需要在CLI模式下运行,nohup虽然可以在保持在后台一直运行,即时退出登录,但是不太便于管理,故搜索了下Linux守护进程管理工具,发现Supervisor,总体感觉挺好用的,所以分享给更多的人使用。...
  • 守护进程Linux系统开发中很重要的知识点,很多朋友对这个问题掌握的不是很深入,今天我就写写这方面的问题,可以帮助大家熟悉守护进程编写过程。
  • Linux守护进程编写.pdf
  • 六.linux进程之守护进程

    千次阅读 2019-04-27 16:41:04
    1.Linux系统守护进程的创建流程: 1、后台运行 2、脱离控制终端、登录会话和进程组 3、改变当前工作目录 4、umask设置为0以取消任何文件权限屏蔽 5、关闭所有文件描述符 6、将0、1、2定位到/dev/null 2、守护...
  • 原文:http://blog.csdn.net/djstavaV/article/details/47810445软硬件环境Ubuntu ...典型的守护进程一般都会在进程名后加上字母”d”,表示daemon,如常见的mysqld、telnetd、sshd等。这些进程没有控制终端,不受用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,252
精华内容 11,700
关键字:

linux编写守护进程

linux 订阅