Linux进程控制

2021SC@SDUSC

项目环境:

  1. 树莓派4b
  2. 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 种不同类型的信号。

《深入理解计算机系统》图 8-26

 下面列出测试代码:

#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 的键盘中断信号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值