Linux-终端、作业控制与守护进程

来源:互联网 发布:php高级视频教程下载 编辑:程序博客网 时间:2024/06/05 11:12

1.进程组
每个进程除了有一个进程ID之外,还属于一个进程组.进程组是一个或者多个进程的集合.
通常他们与同一作业相关联,可以接受来自同一终端的各种信号.每个进程组有一个唯一的进程组ID,每个进程组都可以有一个组长进程.标识为:其进程组ID等于其进程ID
组长可以创建一个进程组,创建其中的进程,然后终止.只要组内有进程,则该进程就存在,与组长存亡无关
2.作业
Shell分前后台控制的不是进程而是作业(Job)或者进程组(Process Group).一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成.shell可以运行一个前台作业和任意多个后台作业,这称为作业控制.作业与进程组的区别:如果作业中的某个进程创建了子进程,那么子进程不属于作业.而作业运行结束,shell就将自己提到前台,如果原先的前台进程还存在(子进程),他就自动变为后台进程组.
代码实现:

#include<stdio.h>#include<stdlib.h>#include<unistd.h>int main(){    pid_t id=fork();    if(id==0){        while(1){            printf("I am child!\n");            sleep(1);        }    }else{        printf("I am father!\n");        sleep(3);        exit(0);    }    return 0;}

这里写图片描述

3.会话
会话是一个或者多个进程组的集合
一个会话可以有一个控制终端.也即是登录到其上的终端设备.
建立与控制终端连接的会话称为控制进程
一个会话应该包括一个控制进程(会话首进程),一个前台进程组和任意后台进程组
内核可以发送响应的信号给前台进程组中的所有进程
① $ proc1 | proc2 &

② $ proc3 | proc4 | proc5
其中proc1与proc2属于同⼀个后台进程组, proc3, proc4和proc5属于同⼀个前台进程组,
Shell本⾝属于⼀个单独的进程组。这些进程组的控制终端相同,它们同属于⼀个会话,当
⽤户在控制终端输⼊特殊的控制键(如Ctrl+C,产⽣SIGINT,Ctrk+,产⽣SIGQUIT,Ctrl+Z,
产⽣SIGTSTP), 内核发送相应的信号给前台进程组中的所有进程。
4.终端
unix系统中,用户通过终端登录到系统后得到一个shell进程.这个终端成为shell的控制终端,控制终端是保存在pcb中的信息,而fork会复制pcb信息,所以由当前shell启动的其他进程的控制终端也是这个终端,每个进程都可以通过访问/dev/tty访问他的控制终端. 默认情况 下(没有重定向),每个进程的标准输⼊、标准输出和标准错误输出都指向控制终端,进程从标准输⼊读也就是读⽤户的键盘输⼊,进程往标准输出或标准错误输出写也就是输出到显⽰器上。此外在控制终端输⼊⼀些特殊的控制键可以给前台进程发信号,例如Ctrl-C:SIGINT,Ctrl-\表⽰SIGQUIT。
ttyname函数可以由文件描述符查处对应的文件名(查看终端对应的设备)

#include<stdio.h>#include<stdlib.h>#include<unistd.h>int main(int argc, char const *argv[]){     printf("fd: %d ->%s\n",0, ttyname(0));     printf("fd: %d ->%s\n",1, ttyname(1));     printf("fd: %d ->%s\n",2, ttyname(2));     return 0;}

终端1
这里写图片描述
再开一个终端
这里写图片描述

6.守护进程
守护进程也称精灵进程(Daemon),是运⾏在后台的⼀种特殊进程。它独⽴于控制终端并且周期性地执⾏某种任务或等待处理某些发⽣的事件。守护进程是⼀种很有⽤的进程。
Linux的⼤多数服务器就是⽤守护进程实现的。⽐如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任务。比如,作业规划进程crond等
Linux系统启动时会启动很多系统服务进程,这些系统服 务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束用户户注销时终止,但系统服务进程不受用户登录注销的影响,它们⼀直在运⾏着。这种进程有⼀个名称叫守护进程(Daemon)。
创建守护进程
创建守护进程最关键的⼀步是调⽤setsid函数创建⼀个新的Session,并成为Session Leader。
该函数调⽤成功时返回新创建的Session的id(其实也就是当前进程的id),出错返回-1。注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进程组的Leader也很容易,只要先fork再调用setsid就行了。 fork创建的子进程和⽗进程在同⼀个进 程组中,进程组的Leader必然是该组的第⼀个进程,所以子进程不可能是该组的第⼀个进程,在子进程中调用setsid就不会有问题了。
成功调用该函数的结果是:
①创建⼀个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
②创建⼀个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
③如果当前进程原本有⼀个控制终端,则它失去这个控制终端,成为⼀个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是⼀个普通的打开⽂件而不是控制终端了。
创建守护进程:
①调用umask将文件模式创建屏蔽字设置为0
②调用fork,父进程退出(让shell以为程序结束,shell作为前台进程;;保证子进程是一个进程组的组长).
③调用setsid创建一个新会话.(导致,1新会话首进程,2称为进程组长,3调用进程没有控制终端(再次fork保证daemon之后不会打开tty设备))
④当前工作目录更改为跟目录
⑤关闭不需要的文件描述符
⑥忽略SIGCHLD信号

自己创建守护进程代码:

#include<stdio.h>#include<stdlib.h>#include<unistd.h>void mydaemon(){    umask(0);    if(fork()>0){        exit(0);    }    setsid();    chdir("/");}int main(){    mydaemon();    while(1);    return 0;}

这里写图片描述
调用Unix标准

#include <stdio.h>#include<unistd.h>int main(){   daemon(0,0);   while(1);}
阅读全文
0 0
原创粉丝点击