进程间关系:
进程组:
一个或多个进程的集合。进程组中有一个进程是组长进程,进程组的id就等于这个进程的pid
进程组并不会随着组长进程的退出而退出,而是组中所有进程退出后才会退出。
ctrl+c针对的前台进程组中所有进程,(s+)
./main & 变成后台进程 (s)
这里写图片描述
进程:2444 、2444;
组长:2444,进程组第一个进程;
PID:线程组ID
PGID:进程组id,进程组内所有进程都有相同的PGID,等于该组组长的PID;
ps选项:a:不仅列出当前用户的进程,也列出所有其他用户的进程;
x: 表示不仅列出有控制终端的进程,也列出所有无控制终端的进程;
j :表示列出与作业控制相关的信息。
如果kill -2 2444中断组长或者kill -9 2444杀掉组长,进程组还在,其他进程也在。
这里写图片描述
作业:
是一个或多个进程的集合。
一个终端前后台的控制不仅仅是进程组还有作业。
一个终端有前台作业,也有后台作业,但是前台作业只有一个。
一般情况下shell是终端的前台作业,当运行了一个命令,那么这个命令将成为前台作业,bash将成为后台作业(因此这时输入的命令将不被执行),当命令运行完毕,bash又成为前台作业。
作业和进程组区别:
前台进程的子进程是不属于前台作业的,但是他们属于同一个进程组。
作业是干活的,一个终端下有两类干活的进程,一类是前台干活,一类是后台干活,因此作业的分类有前台作业和后台作业。
一个终端中,前后台控制是通过作业和进程组完成的。
一个终端中,前台作业有且只有一个,后台作业可以有多个。


//前台作业/shell 及作业和进程组区别

#include<stdio.h>
#include<unistd.h>

int main()
{
        pid_t pid=fork();
        if(pid<0)
        {   
                return -1;
        }   
        else if(pid==0)
        {   
                while(1)
                {   
                        printf("child\n");
                        sleep(1);
                }   
        }   
        else
     {   
                int i=5;
                while(i)
                {   
                        printf("parent\n");
                        sleep(1);
                        i--;
                }   
        }   
        return 0;
}
当程序跑起来后,在前台新起了1个作业,包含父子两个进程。
5秒之内,shell无法接受任何命令,说明此时的前台作业不是shell,因为此时shell变为后台作业。
5秒后,父进程退出,子进程还在运行,但是此时输入命令,shell可以接受进行处理,说明此时shell变为了前台作业,
又因为前台作业只有一个,那么子进程就会变成后台作业。
但是进程所属的进程组还在,组长是父进程(虽然父进程退出,但是其他进程还在,进程组还在)
那么进程组和作业区别是:前台进程的子进程是不属于前台作业的,但是他们属于同一个进程组。
注:可以kill 杀掉子进程    

会话:
实际上可以说成一个会话周期。
对于登录,登录成功则开始一个会话,可能会有一个终端,其中这个会话中有一个会话首进程,这个进程是shell(bash),这个进程将会话与终端联系起来。
一个会话中会有一个前台进程组和任意多个后台进程组。
登录成功之后所运行的进程都是属于会话。
作业控制:
shell分前后台控制的不是进程而是作业或者进程组,一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成,shell可以同时运行一个前台作业和多个后台作业,这称为作业控制。
与作业控制有关的信号(通过实验来理解相关信号):
这里写图片描述
jobs命令可以查看当前有哪些作业。fg命令可以将某个作业提至前台运⾏行,如果该作业的进程组正在后台运⾏则提至前台运⾏行,如果该作业处于停⽌状态,则给进程组的每个进程发SIGCONT信号使它继续运行。参数%1表 示将第1个作业提⾄至前台运行。
这里写图片描述
将cat放到后台运⾏行,由于cat需要读标准输入(也就是终端输入),⽽而后台进程是不能读终端输入的,因此内核发 SIGTTIN信号给进程,该信号的默认处理动作是使进程停止。
守护进程(精灵进程)
守护进程也称精灵进程,是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。

孤儿进程———>建立新的会话——>关闭描述符-——>重新设置当前工作路径——>设置文件的默认创建掩码——>成功逆袭成为守护进程
1.后台运行
2.脱离与终端的关系,脱离原会话,不受原会话和终端的影响。
父进程退出,子进程成为孤儿进程,孤儿进程为了逆袭。就要脱离原会话,因此需要建立新会话。
创建守护进程:
创建守护进程的关键是调用setsid函数创建一个新的Session,并成为Session Leader。


#include <unistd.h>
pid_t setsid(void);

该函数调用成功时返回新创建的Session的id(其实是当前进程的id),出错返回-1。
注:调用这个函数之前,当前进程不允许是进程组的组长,否则该函数返回-1。要保证当前进程不是进程组的组长,只要在fork之后调用setsid即可。fork创建的子进程和父进程在同一个进程组中,进程组的组长必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,在子进程中调用setsid就不会有问题。
成功调⽤用该函数的结果是:创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开⽂文件而不是控 制终端了。
daemon 创建守护进程 。
nochdir :是否要修改当前工作路径。
noclose :是否要关闭描述符。


标签: none

相关文章推荐

添加新评论,含*的栏目为必填