查看内核可以发送多少种信号的命令: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;
}