笔记四:进程间的通信(信号)
2017-02-26 16:36
204 查看
通信对象:信号
用户空间是不能发送信号必须通过内核,不像前面管道通信需要创建,而是信号已经存在于内核中
linux内核总共可以发送64种信号
查看内核可以发送多少种信号:kill -l
1)A要发送信号给B,必须告诉内核要发送什么信号(信号的id号);
2)告诉内核发送给谁;(pid号)
三:信号
信号通信,其实就是内核向用户空间进程发送信号,只有内核才能发信号,用户空间进程不能发送信号。
内核可以发送多少种信号呢?
kill -l
命令:kill -9 pid 或者 killall 进程名 功能: 杀死一个进程
信号通信的框架(A发送信号,B接收信号,怎么处理)
信号的发送(发送信号进程):kill raise alarm
信号的接收(接收信号进程): pause() sleep while(1)
信号的处理(接收信号进程):signal
1.信号的发送(发送信号进程)
kill 函数:
kill命令的程序实现实例
[align=justify]raise函数 发信号给自己 == kill(getpid(), sig)[/align]
[align=justify]例子1:[/align]
例子2:
#include "signal.h"
#include "sys/types.h"
#include "stdio.h"
int main()
{
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("创建进程失败\n");
return -1;
}
/*对于父进程首先是睡眠(8秒)S状态,8秒后进入R(运行)状态
对于子进程就变成了T状态;
*/
if(pid > 0)
{
sleep(8);//睡眠状态;
while(1);
}
if(pid == 0)
{
printf("raise function before\n");
raise(SIGTSTP);//暂停程序,相当于ctrl+z; T状态
printf("raise function after\n");
exit(0);
}
}
alarm 与 raise 函数的比较:
相同点:让内核发送信号给当前进程
[align=justify]不同点:1.alarm 只会发送SIGALARM信号[/align]
2.alarm 会让内核定时一段时间之后发送信号, raise会让内核立刻发信号
[align=justify] [/align]
[align=justify]3.信号的处理(接收信号进程)[/align]
[align=justify] 收到信号的进程,应该怎样处理?[/align]
[align=justify]2. 信号的接收(接收信号进程)[/align]
[align=justify]接收信号的进程,要有什么条件:要想使接收的进程能收到信号,这个进程不能结束 :[/align]
[align=justify]sleep[/align]
[align=justify]pause:进程状态为S[/align]
[align=justify]while(1) A:忽略[/align]
[align=justify]B:终止进程[/align]
[align=justify]C: 暂停[/align]
[align=justify](1)自己的处理方式:[/align]
[align=justify]自己处理信号的方法告诉内核,这样你的进程收到了这个信号就会采用你自己的的处理方式
signal函数
[/align]
void (*handler)(int) => 函数指针变量,函数的形式:含有一个整形参数,无返回值的函数
[align=justify]signal函数有二个参数,第一个参数是一个整形变量(信号值),第二个参数是一个函数指针,是我们自己写的处理函数;[/align]
这个函数的返回值是一个函数指针。
signal告诉内核两个内容:第一个参数:处理哪个信号
第二个参数:采用什么方式处理这个信号(收到这个信号,先进入处理函数,再回到B中进行处理)
例子:
用户空间是不能发送信号必须通过内核,不像前面管道通信需要创建,而是信号已经存在于内核中
linux内核总共可以发送64种信号
查看内核可以发送多少种信号:kill -l
1)A要发送信号给B,必须告诉内核要发送什么信号(信号的id号);
2)告诉内核发送给谁;(pid号)
三:信号
信号通信,其实就是内核向用户空间进程发送信号,只有内核才能发信号,用户空间进程不能发送信号。
内核可以发送多少种信号呢?
kill -l
命令:kill -9 pid 或者 killall 进程名 功能: 杀死一个进程
信号通信的框架(A发送信号,B接收信号,怎么处理)
信号的发送(发送信号进程):kill raise alarm
信号的接收(接收信号进程): pause() sleep while(1)
信号的处理(接收信号进程):signal
1.信号的发送(发送信号进程)
kill 函数:
[align=justify]所需头文件[/align] | #include <signal.h> [align=justify]#include <sys/types.h>[/align] | |
[align=justify]函数原型[/align] | [align=justify]int kill(pid_t pid, int sig);[/align] | |
[align=justify]函数传入值[/align] | [align=justify]pid:[/align] | [align=justify]正数:要接收信号的进程的进程号[/align] |
0:信号被发送到所有和 pid 进程在同一个进程组的进程 | ||
-1:信号发给所有的进程表中的进程(除了进程号最大的进程外 ) | ||
[align=justify]sig:信号[/align] | ||
[align=justify]函数返回值[/align] | [align=justify]成功:0[/align] | |
[align=justify]出错:-1[/align] |
/*通过命令行参数实现信号的发送 mykill.c*/ #include "signal.h" #include "sys/types.h" #include "stdio.h" #include "stdlib.h" int main(int argc,char *argv[]) { int pid; int sig; if(argc < 3) return -1; pid=atoi(argv[2]);//将字符串转化为整型; sig=atoi(argv[1]+1); printf("pid=%d,sig=%d\n",pid,sig); kill(pid,sig); return 0; }
[align=justify]raise函数 发信号给自己 == kill(getpid(), sig)[/align]
[align=justify]所需头文件[/align] | #include <signal.h> [align=justify]#include <sys/types.h>[/align] |
[align=justify]函数原型[/align] | [align=justify]int raise(int sig);[/align] |
[align=justify]函数传入值[/align] | [align=justify]sig:信号[/align] |
[align=justify]函数返回值[/align] | [align=justify]成功:0[/align] |
[align=justify]出错:-1[/align] |
#include "signal.h" #include "sys/types.h" #include "stdio.h" #include "stdlib.h" int main() { printf("raise before\n");//是一个库函数,只会把raise before写入库缓存,而没有写入内核,没有加\n也不会打印 raise(9);//_exit(); /*当执行raise == kill -9时,下面一条语句肯定不会执行(不会打印出来)*/ printf("raise after\n"); return 0; }
例子2:
#include "signal.h"
#include "sys/types.h"
#include "stdio.h"
int main()
{
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("创建进程失败\n");
return -1;
}
/*对于父进程首先是睡眠(8秒)S状态,8秒后进入R(运行)状态
对于子进程就变成了T状态;
*/
if(pid > 0)
{
sleep(8);//睡眠状态;
while(1);
}
if(pid == 0)
{
printf("raise function before\n");
raise(SIGTSTP);//暂停程序,相当于ctrl+z; T状态
printf("raise function after\n");
exit(0);
}
}
alarm 与 raise 函数的比较:
相同点:让内核发送信号给当前进程
[align=justify]不同点:1.alarm 只会发送SIGALARM信号[/align]
2.alarm 会让内核定时一段时间之后发送信号, raise会让内核立刻发信号
[align=justify]所需头文件[/align] | [align=justify]#include <unistd.h>[/align] |
[align=justify]函数原型[/align] | [align=justify]unsigned int alarm(unsigned int seconds)[/align] |
[align=justify]函数传入值[/align] | [align=justify]seconds:指定秒数[/align] |
[align=justify]函数返回值[/align] | 成功:如果调用此alarm()前,进程中已经设置了闹钟时间,则 [align=justify]返回上一个闹钟时间的剩余时间,否则返回0。[/align] |
[align=justify] [/align] | [align=justify]出错:-1[/align] |
[align=left]信号名[/align] | [align=left]含义[/align] | [align=left]默认操作[/align] |
[align=left]SIGHUP[/align] | [align=left]该信号在用户终端连接(正常或非正常)结束时发出,通常是在终端的控制进程结束时,通知同一会话内的各个作业与控制终端不再关联。[/align] | [align=left]终止[/align] |
[align=left]SIGINT[/align] | [align=left]该信号在用户键入INTR字符(通常是Ctrl-C)时发出,终端驱动程序发送此信号并送到前台进程中的每一个进程。[/align] | [align=left]终止[/align] |
[align=left]SIGQUIT[/align] | [align=left]该信号和SIGINT类似,但由QUIT字符(通常是Ctrl-\)来控制。[/align] | [align=left]终止[/align] |
[align=left]SIGILL[/align] | [align=left]该信号在一个进程企图执行一条非法指令时(可执行文件本身出现错误,或者试图执行数据段、堆栈溢出时)发出。[/align] | [align=left]终止[/align] |
[align=left]SIGFPE[/align] | [align=left]该信号在发生致命的算术运算错误时发出。这里不仅包括浮点运算错误,还包括溢出及除数为0等其它所有的算术的错误。[/align] | [align=left]终止[/align] |
[align=left]SIGKILL[/align] | [align=left]该信号用来立即结束程序的运行,并且不能被阻塞、处理和忽略。[/align] | [align=left]终止[/align] |
[align=left]SIGALRM[/align] | [align=left]该信号当一个定时器到时的时候发出。[/align] | [align=left]终止[/align] |
[align=left]SIGSTOP[/align] | [align=left]该信号用于暂停一个进程,且不能被阻塞、处理或忽略。[/align] | [align=left]暂停进程[/align] |
[align=left]SIGTSTP[/align] | [align=left]该信号用于暂停交互进程,用户可键入SUSP字符(通常是Ctrl-Z)发出这个信号。[/align] | [align=left]暂停进程[/align] |
[align=left]SIGCHLD[/align] | [align=left]子进程改变状态时,父进程会收到这个信号[/align] | [align=left]忽略[/align] |
[align=left]SIGABORT[/align] | [align=left]该信号用于结束进程[/align] | [align=left]终止[/align] |
[align=justify] 收到信号的进程,应该怎样处理?[/align]
[align=justify]2. 信号的接收(接收信号进程)[/align]
[align=justify]接收信号的进程,要有什么条件:要想使接收的进程能收到信号,这个进程不能结束 :[/align]
[align=justify]sleep[/align]
[align=justify]pause:进程状态为S[/align]
[align=justify]while(1) A:忽略[/align]
[align=justify]B:终止进程[/align]
[align=justify]C: 暂停[/align]
[align=justify](1)自己的处理方式:[/align]
[align=justify]自己处理信号的方法告诉内核,这样你的进程收到了这个信号就会采用你自己的的处理方式
signal函数
[/align]
[align=left]所需头文件[/align] | [align=left]#include <signal.h>[/align] |
[align=left]函数原型[/align] | [align=left]void (*signal(int signum, void (*handler)(int)))(int);[/align] |
[align=left]函数传入值[/align] | [align=left]signum:指定信号[/align] |
[align=left]handler:[/align] | [align=left]SIG_IGN:忽略该信号。[/align] |
[align=left]SIG_DFL:采用系统默认方式处理信号。(终止进程)[/align] | |
[align=left]自定义的信号处理函数指针[/align] | |
[align=left]函数返回值[/align] | [align=left]成功:设置之前的信号处理方式[/align] |
[align=left]出错:-1[/align] |
[align=justify]signal函数有二个参数,第一个参数是一个整形变量(信号值),第二个参数是一个函数指针,是我们自己写的处理函数;[/align]
这个函数的返回值是一个函数指针。
signal告诉内核两个内容:第一个参数:处理哪个信号
第二个参数:采用什么方式处理这个信号(收到这个信号,先进入处理函数,再回到B中进行处理)
例子:
#include "signal.h" #include "sys/types.h" #include "stdio.h" #include "stdlib.h" void myfun(int sig) { int i; for(i=0;i<5;i++) { sleep(1); printf("recv sig:%d0,i=%d\n",sig,i); } return; } int main() { int i=0; /*首先程序正常运行,当用户从键盘敲入Ctrl+C时,程序将会跳转到自定义函数myfun中运行,执行完myfun程序,程序将再跳转到main函数中做自己的事(继续运行); */ signal(SIGINT,myfun);//SIGINT信号为 SIGINT 该信号在用户键入INTR字符(通常是Ctrl-C)时发出,终端驱动程序发送此信号并送到前台进程中的每一个进程。 终止 while(1) { sleep(1); i++; printf("main function process things,i=%d\n",i); } return 0; }
相关文章推荐
- 进程之间的信号通信,类型、处理机制笔记
- 孙鑫VC学习笔记:第十七讲 用命名管道实现进程间的通信
- 孙鑫VC学习笔记:第十七讲 (四) 用邮槽实现进程间的通信
- 进程通信之(一) 信号机制实验
- Linux进程通信 发送信号
- 进程通信之(一,二) 信号机制实验
- 孙鑫VC学习笔记:第十七讲 用剪贴板实现进程间的通信
- 非亲缘进程间的共享内存与信号通信
- Linux进程通信----学习笔记(一)
- linux 进程通信-信号学习总结(1)
- 进程通信之信号篇 signal
- 孙鑫VC学习笔记:第十七讲 (三) 用命名管道实现进程间的通信
- 进程通信之信号(上)
- 孙鑫VC视频教程笔记之第十七课“进程间的通信”
- Linux进程通信---学习笔记(二)
- 孙鑫VC学习笔记:第十七讲 用邮槽实现进程间的通信
- 进程通信之(一) 信号机制实验
- 基本进程通信--信号
- Linux 系统编程笔记 守护进程,进程通信
- 父进程与子进程间的信号通信