2021SC@SDUSC
项目环境:
- 树莓派4b
- Ubuntu Desktop 21.04
进程控制:
1. 创建进程:
在Linux 系统中,父进程通过调用fork函数创建一个新的运行的子进程。
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
关于fork函数,有如下特性:
子进程得到与父进程用户级虚拟地址空间相同的(但是独立的)一份副本,包括代码和数据段、堆、共享库以及用户栈。子进程还获得与父进程任何打开文件描述符相同的副本,这就意味着当父进程调用fork时,子进程可以读写父进程中打开的任何文件。父进程和新创建的子进程之间最大的区别在于它们有不同的PID。
—— 《深入理解计算机系统》
下面列出测试文件processTest.c的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int i = 100;
pid = fork();
if(pid == -1)
{
printf("Creat fork error!!!\n");
exit(1);
}
else if(pid)
{
i++;
printf("The father i = %d.\n",i);
printf("The father return %d.\n",pid);
printf("The father pid is %d.\n",getpid());
printf("The father ppid is %d.\n",getppid());
while(1); //避免进程退出
}
else
{
i++;
printf("\nThe child i = %d.\n",i);
printf("The child return %d.\n",pid);
printf("The child pid is %d.\n",getpid());
printf("The child ppid is %d.\n",getppid());
while(1); //避免进程退出
}
return 0;
}
根据以上代码后,我们使用如下命令生成可执行文件:
gcc processTest.c o processTest
在Ubuntu Desktop下运行结果如图:
?为什么会产生这种结果呢?在CSAPP中,已经给出了解答:
- 调用一次,返回两次。fork函数被父进程调用一次,但是却返回两次——一次是返回到父进程,一次是返回到新创建的子进程。
- 并发执行。父进程和子进程是并发运行的独立进程。内核能够以任意方式交替执行
它们的逻辑控制流中的指令。 - 相同但是独立的地址空间。两个进程的地址空间都是相同的。每个进程有相同的
用户栈、相同的本地变量值、相同的堆、相同的全局变量值,以及相同的代码。 - 共享文件。父进程和子进程都把它们的输出显示在屏幕上。原因是子进程继承了父进程所有的打开文件。当父进程调用fork时,stdout文件是打开的,并指向屏幕。子进程继承了这个文件,因此它的输出也是指向屏幕的。
——《深入理解计算机系统》
?这就不难理解为什么会产生如图的输出结果。
2.?进程软中断通信
Linux中的信号一个正实数,它定义在系统头文件<signal.h>中 ,它一般用来通知某进程有中断异常。下图展示了Linux系统支持的30 种不同类型的信号。
?
?下面列出测试代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
int wait_mark;
void stop(){
wait_mark = 0;
}
void waiting(){
while(wait_mark == 1);
}
int main(){
int p1, p2;
while((p1 = fork()) == -1);
if(p1 == 0){
wait_mark = 1;
signal(SIGINT, SIG_IGN);
signal(16, stop);
waiting();
printf("\nchild process p1 is killed by parent!\n");
sleep(3);
exit(0);
}else{
while((p2 = fork()) == -1);
if(p2 == 0){
wait_mark = 1;
signal(SIGINT, SIG_IGN);
signal(17, stop);
waiting();
printf("\nchild process p2 is killed by parent!\n");
sleep(3);
exit(0);
}else{
wait_mark = 1;
signal(SIGINT, stop);
waiting();
kill(p1, 16);
kill(p2, 17);
wait(0);
wait(0);
printf("\nparent process is killed !\n");
exit(0);
}
}
}
运行结果如下:
在本实验当中,创建 2 个进程,通过系统调用 signal() 捕捉键盘上的中断信号。捕捉到中断信号后,父进程用系统调用 kill()?向两个子进程发出信号,子进程捕捉到信号后分别输出信息后终止 。可以看到,我们让子进程 1 接受父进程软中断信号 17 然后转向 stop() 函数,而如果 等待标记不为 0 那么就一直等待父进程的信号 ,其中非常重要的一部就是 signal(SIGINT, SIG_IGN) ,它实现了屏蔽 ctrl+c 的键盘中断信号。
|