LINUX 进程软中断
我们这里使用这段程序通过软中断进程的方式来帮助我们更加深层的理解进程.
代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
int wait_flag;
void stop();
int main(){
int pid1,pid2;
wait_flag=1;
signal(2,stop); //or sign(14,stop);
while(wait_flag==1);
while((pid1=fork())==-1);
if(pid1>0)
{
while((pid2=fork())==-1);
if(pid2>0){
wait_flag=1;
sleep(5);
kill(pid1,16);
kill(pid2,17);
wait(0);
wait(0);
printf("Parent process is killed !!!\n");
exit(0);
}
else{
wait_flag=1;
signal(17,stop);
while(wait_flag==1);
printf("Child process 2 is killed by parent !!\n");
exit(0);
}
}
else{
wait_flag=1;
signal(16,stop);
while(wait_flag==1);
printf("Child process 1 is killed by parent !!\n");
exit(0);
}
}
void stop() {
wait_flag=0;
}
首先先对我们的函数进行分析:
1.wait()函数
#include<sys/types.h>
#include<wait.h> //头文件
pid_t wait(int *status) //函数原型
(pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)
函数功能是: 父进程一旦调用了wait就立即阻塞自己,由wait自动分析当前进程的某个子进程是否已经退出,如果让它找到了这样一个子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
2.signal函数
#include<signal.h> //头文件
void (*signal(int sig, void (*func)(int)))(int) //函数原型
sighandler_t signal(int signum, sighandler_t handler)
//用typedef处理过的signal函数
signal函数可以设置程序对信号的处理方式。
signal函数中的参数:
- signum是表示信号的编号
- handler表示信号的处理方式 ,其中处理方式有三种:
① SIG_IGN:忽略参数 s i g n u m signum signum所指的信号。
② 一个自定义的处理信号的函数,信号的编号为这个自定义函数的参数。
③ SIG_DFL:恢复参数 s i g n u m signum signum所指信号的处理方法为默认值。
3.sleep函数
#include<unistd.h> //头文件
unsigned int sleep (unsigned int seconds) //函数原型
进程执行挂起一段时间,也就是等待一段时间在继续执行。(参数 seconds seconds seconds单位为秒)
4.kill函数
#include<sys/types.h>
#include<signal.h> //头文件
int kill(pid_t pid, int sig) //函数原型
kill函数 用于在程序中向其它进程或者线程发送信号。
参数 pid 有几种情况:
①pid > 0将信号传给进程号为 p i d pid pid 的进程。
②pid=0将信号传给和目前进程相同进程组的所有进程,常用于父进程给子进程发送信号,注意,发送信号者进程也会收到自己发出的信号。
③pid=−1 将信号广播传送给系统内所有的进程,例如系统关机时,会向所有的登录窗口广播关机信息。
参数sig用作准备发送的信号代码。
返回值:
成功执行时,返回 0;
失败时返回 -1。
让我们对这段代码进行分析:
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
int wait_flag;
void stop();
int main(){
int pid1,pid2;
wait_flag=1;
signal(2,stop); //or sign(14,stop);
while(wait_flag==1);
while((pid1=fork())==-1);
if(pid1>0)
{
while((pid2=fork())==-1);
if(pid2>0){
wait_flag=1;
sleep(5);
kill(pid1,16);
kill(pid2,17);
wait(0);
wait(0);
printf("Parent process is killed !!!\n");
exit(0);
}
else{
wait_flag=1;
signal(17,stop);
while(wait_flag==1);
printf("Child process 2 is killed by parent !!\n");
exit(0);
}
}
else{
wait_flag=1;
signal(16,stop);
while(wait_flag==1);
printf("Child process 1 is killed by parent !!\n");
exit(0);
}
}
void stop() {
wait_flag=0;
}
看运行结果可以看出“Child process 2 is killed by parent !!”和“Child process 1 is
killed by parent !!”的次序会变化,而“Parent process is killed
!!”次序不会变,总是在最后输出。
对这段程序进行分析: 按顺序运行这段程序,遇到 **signal(2,stop)**这个函数,他的作用是输入两次 ctrl+c 就执行stop这个函数,看到代码最下面的部分,我们可以知道stop函数的作用是将 wait_flag 赋值为0,故而跳出下面一行的while循环并开始创建子进程,我们暂称为子进程1;看向父进程,父进程再次创建一个子进程,并称为子进程2 ,由于pid2 > 0,故进入if语句内,首先遇到sleep函数,等待五秒后,执行两个kill函数,分别把16,17传给pid1和pid2两个子进程,然后遇到wait函数,父进程2进入等待,需要等子进程执行完毕;看向子进程2,因为收到kill发送过来的’17’信号量,故signal函数执行,stop函数执行,使wait_flag
为0,跳出循环,并打印语句"Child process 2 is killed by parent",子进程2执行完毕之后回到父进程2,再次遇到wait函数,需要先执行完子进程1;子进程1操作与子进程2操作类似,这里不做说明.然后回到父进程2打印语句"Parent process is killed !!!"结束运行.由此我们可以知道语句"Parent process is killed !!!"总是在最后执行,而另外两个子进程因为是同时进行运行,故而运行多次的结果是不一样的