进程通信之对象-信号通信

查看内核可以发送多少种信号的命令:kill -l

每种信号代表不同的功能和意义。杀死某个进程是命令:kill [进程号] [pid]

1,信号的发送:kill(),raise(),alam()等函数
2,信号的接收:pause() sleep() while()
3,信号的处理: signal()
1,信号的发送


例子1:用kill()函数实现kill命令功能;建立mykill()文件,内容如下。

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"

int main(int argc,char *argv[])
{
        int signal;
        int pid;
        if(argc<3)
        {
        printf("please input param\n");
        return -1;
        }
        sig=atio(argv[1]);//atio将字符型转换为整型
        pid=atio(argv[2]);
        
        kill(pid,signal);//调用系统函数kill杀死进程
        return 0;
  }

编译生成mykill,此时运行:./mykill [pid] [signal]等价于kill [pid] [signal] 。
1,运行:ps -axj查看系统正在运行的进程,杀死任意进程。这里试着杀死我们运行的进程./no2。

9代表9号进程,具有终止进程功能。kill -9 27243成功杀死进程进程编号27243的进程./no2.

例子2:raise函数的用法。建立raise.c内容如下

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"

int main()
{
    printf("raise before");//行缓存只是写入库缓存
    raise(9);//等价于_exit()中止自身
    printf("raise after");
    return 0;
 }

例子2:raise()函数的应用,僵死进程演示
【注】waitpid()函数是等待子进程的结束;wait()负责回收子进程资源。

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"

int main()
{
    pid_t pid;
    pid=fork();
    if(pid>0)
    {
        sleep(8);               //阻塞方式
        if(waitpid(pid,NULL,WNOHANG) == 0)//等待子进程结束
        {
            kill(pid,9);//杀死子进程
        }
        while(1);
    }
    if(pid == 0)
    {
     printf("raise before\n");
    raise(SIGTSTP);//暂停交互进程相当于ctrl+z
    printf("raise after");
    exit(0);
    }
   return 0;
}

运行./raise,并ps -axj查看./raise的运行状态,结果如下图:
前8秒。

8秒后。

前8秒父进程为S+(睡眠状态),子进程处于T+(暂停状态);8秒后父进程处于R+(运行状态),子进程处于Z+(僵尸状态:由于子进程被kill()中制结束,而父进程进入死循环而不能结束,从而导致子进程所占用的资源得不到回收释放而导致);

接下来在kill()之后调用wait()函数回收子进程,而从防止子进程进入僵尸状态。

if(pid>0)
    {
        sleep(8);
        if(waitpid(pid,NULL,WNOHANG) == 0)
        {
            kill(pid,9);//杀死子进程
        }
        wait(pid);//回收子进程资源
        while(1);

结果子进程被释放:

例子3:alarm()函数的应用;创建alarm.c,内容如下;

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"

int main()
{
int i;
i=0;
printf("alarm before\n");
alarm(9);//定时9秒,9秒后收到alarm发送的信号,然后进程终止
printf("alarm after\n");
while(i<20)
{
    i++;
    sleep(1);//每循环一次睡眠一秒,循环20次则花20秒,以保证alarm9秒后发送信号时,程序还在运行
    printf("processing something  i=%d\n",i);
}
return 0;
}

结果,9秒后。alarm发送SIGALRM信号给当前正在运行的./alarm进程。

./alarm收到信号后,终止当前./alarm进程。

1信号的接收

例子:pause(),sleep()函数的用法;

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"

int main()
{
int i;
i=0;
printf("pause before\n");
pause();//进程永久睡眠,,后面语句将不会被执行,需要被唤醒,ctrl+c
printf("pause after\n");
while(i<20)
{
    i++;
    sleep(1);
    printf("processing something  i=%d\n",i);
}
return 0;
}

运行结果:pause before
./a.out处于S+(睡眠状态)。

3,信号的处理


signal()函数的解析:

例子:signal()函数的应用,基于alarm.c,实现main()主函数打印8条语句后,第9秒时alarm(9)函数向进程./alarm自身发送14号信号(14号即alarm本身),此时调用signal处理该信号从而触发myfun()函数,执行完myfun()函数之后,返回main()函数继续执行while()循环直至进程结束;
建立signal.c文件,实现代码如下:

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"
void myfun(int signum)//自己定义的处理函数
{
    int i;
    i=0;
    while(i<10)
    {
    printf("process signal signum=%d\n",signum);
    sleep();
    i++;
    }
    return;//return to main()
 }
int main()
{
int i;
i=0;
signal(14,myfun);//告诉内核处理的方式一
printf("alarm before\n");
alarm(9);//定时9秒,9秒后收到alarm发送的信号,然后进程终止
printf("alarm after\n");
//signal(14,SIG_IGN);//告诉内核处理的方式二,9秒后还会继续执行main()函数,不会执行myfun
//signal(14,SIG_DFL);//告诉内核处理的方式三,9秒后会终止进程
while(i<20)
{
    i++;
    sleep(1);//每循环一次睡眠一秒,循环20次则花20秒,以保证alarm9秒后发送信号时,程序还在运行
    printf("processing something  i=%d\n",i);
}
return 0;
}

以上为信号通信的发送接收以及处理。

综合例子:子进程通过kill()函数让内核向主进程发送信号,主进程接收到信号后,采用自己的方式处理,跳到myfun()函数运行代码,运行完后返回主进程:
建立signal2,c文件,如下:

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"
void myfun(int signum)//自己定义的处理函数
{
    int i;
    i=0;
    while(i<6)
    {
    printf("receive  signum=%d,i=%d\n",signum,i);
    sleep(1);
    i++;
    }
    return;//return to main()
 }
int main()
{
pid_t pid;
pid=fork();
if(pid>0)//parent code
{
int i;
i=0;
signal(10,myfun);//父进程处理10号信号,调用自定函数myfun
while(1)
{
printf("parent process things,i=%d\n",i);
sleep(1);
++i;
}
}
if(pid ==0)//child code
{
sleep(10);
kill(getppid(),10);//获取父进程IP,发送系统默认的10信号给父进程
sleep(10);
exit(0);
}
return 0;
}

为里解决子进程变成僵尸进程,利用exit(0);语句等价于kill(getppid,17),建立myfun1();回收子进程的资源,解决僵尸进程。添加代码如下

#include"sys/types.h"
#include"signal.h"
#include"unistd.h"
#include"stdio.h"
#include"stdlib.h"
void myfun(int signum)//自己定义的处理函数
{
    int i;
    i=0;
    while(i<6)
    {
    printf("receive  signum=%d,i=%d\n",signum,i);
    sleep(1);
    i++;
    }
    return;//return to main()
 }
void myfun1(int signum)//solve the child 'Z+'
{
        printf("receive signum=%d\n",signum);
        wait(NULL);
        return;
}
int main()
{
        pid_t pid;
        pid=fork();
        if(pid>0)//parent code
        {
        int i;
        i=0;
        signal(10,myfun);//父进程处理10号信号,调用自定函数myfun
        signal(17,myfun1);//receive signal from exit(0);
        while(1)
        {
        printf("parent process things,i=%d\n",i);
        sleep(1);
        ++i;
        }
        }
        if(pid ==0)//child code
        {
        sleep(10);
        kill(getppid(),10);//获取父进程IP,发送系统默认的10信号给父进程
        sleep(10);
        exit(0);//kill SIGCHLD to parent === kill(getpid(),17)
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值