解释: 所有seep进程的ppid都是bash,都属于同一个bash会话,同时创健建的sleep1,2,3属于同一个组,他们三个自成一组;他们三个合作起来共同完成一个任务,他们的组长是19561,pid == PGRP,组长是启动的第一个进程。
(1) 前台进程 和 后台进程
①前台进程,./运行时 , 默认将程序放到前台运行,在前台运行的进程的状态后有一个 + 号
②一个终端只能有一个前台进程,为什么把一个进程放到前台之后,且我们输入的命令不起作用?(你把一个进程放到前台,bash自动变成后台进程)我们的前台进程以前是bash,只有在前台的时候才能接收你的命令,到了后台接收不了
③后台进程, ./运行时在后面加上&,可以指定将程序放到后台运行,后台运行的进程的状态后没有+
号。
④将程序放到后台运行时会发现多了一行提示信息
[1] 17353
其中[1]是作业的编号,如果同时运行多个作业可以用这个编号进行区分,17353是该作业中某个进程的id(一个作业可以由多个进程组成)。
(2)jobs , fg , bg
①使用jobs命令查看当前会话中有哪些作业
②使用 fg 命令(foreground),可以将某个作业提至前台运行,如果该作业正在后台运行则直接提至前台运行,如果该作业处于停止状态,则给进程组的每个进程发SIGCONT信号使它继续运行并提至前台。
③使用 bg 命令,可以让某个停止的作业在后台继续运行(Running),本质就是给该作业的进程组的每个进程发SIGCONT信号
(3)ps指令查看指定选项
①携带-o选项,可以查看指定的信息。
②关于会话
使用ps axj 查看系统中的进程:
(1)创建步骤如下:
(2)相关说明:
(3)代码
- #include <fcntl.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <stdlib.h>
-
- int main()
- {
- //1、设置文件掩码为0
- umask(0);
-
- //2、fork后终止父进程,子进程创建新会话
- if (fork() > 0){ //father
- exit(0);
- }
-
- setsid();
-
- //3、忽略SIGCHLD信号,
- signal(SIGCHLD, SIG_IGN);
-
- //4、再次fork,终止父进程,保持子进程不是会话首进程,从而保证后续不会再和其他终端相关联
- //防御性操作,不是必须的
-
- if (fork() > 0){
- //father
- exit(0);
- }
-
- //5、更改工作目录为根目录(可选的选项)
- chdir("/");
-
- //6、将标准输入、标准输出、标准错误重定向到/dev/null(可选的选项)
- close(0);
- int fd = open("/dev/null", O_RDWR);
- dup2(fd, 1);
- dup2(fd, 2);
-
- while (1);
- return 0;
- }
(4)结果
④找到该进程对应的进程文件 ,可以看到该进程的工作目录已经成功改为了根目录。
⑤在该进程文件中 , 可以看到该进程的标准输入、标准输出以及标准错误也成功重定向到了/dev/null。
我们创建守护进程时可以直接调用daemon接口进行创建,daemon函数的函数原型如下:
int daemon(int nochdir, int noclose);
参数说明:
- 如果参数nochdir为0,则将守护进程的工作目录该为根目录,否则不做处理。
- 如果参数noclose为0,则将守护进程的标准输入、标准输出以及标准错误重定向到/dev/null,否则不做处理
(1)使用示例
- #include <unistd.h>
-
- int main()
- {
- daemon(0, 0);
- while (1);
- return 0;
- }
(2)结果
只需要设置两个参数nochdir和noclose,当所给nochdir为0时,我们将守护进程的工作目录该为根目录,当所给noclose为0时,我们则将守护进程的标准输入、标准输出以及标准错误重定向到/dev/null
- #include <fcntl.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <stdlib.h>
-
- void my_daemon(int nochdir, int noclose)
- {
- //1、设置文件掩码为0
- umask(0);
-
- //2、fork后终止父进程,子进程创建新会话
- if (fork() > 0){
- //father
- exit(0);
- }
-
- setsid();
-
- //3、忽略SIGCHLD信号
- signal(SIGCHLD, SIG_IGN);
-
- //4、再次fork,终止父进程,保持子进程不是会话首进程,从而保证后续不会再和其他终端相关联
- //(不是必须的,防御性编程)
-
- if (fork() > 0){
- //father
- exit(0);
- }
-
- //5、更改工作目录为根目录(可选的选项)
- if (nochdir == 0){ //判断1
- chdir("/");
- }
-
- //6、将标准输入、标准输出、标准错误重定向到/dev/null(可选的选项)
- if (noclose == 0){ //判断2
- close(0);
- int fd = open("/dev/null", O_RDWR);
- dup2(fd, 1);
- dup2(fd, 2);
- }
- }
-
- int main()
- {
- my_daemon(0, 0);
- while (1);
- return 0;
- }