进程间通信 ===》信号通信
1. 64个信号
应用:异步通信。 中断,, (PCBC块中,64个信号,大部分是:关闭,暂停,继续)
linux@ubuntu:~$ kill -l (9/19带有强制性,其余具有滞后性,可能稍滞后)
1) SIGHUP 2) SIGINT(关闭:类似于ctrl c) 3) SIGQUIT 4) SIGILL 5) SIGTRAP (ring 0 ,ring 3)
6) SIGABRT(系统触发错误) 7) SIGBUS(总线错误) 8) SIGFPE(算数错误) 9) SIGKILL(重点:强制关闭)10) SIGUSR1(用户自定义)
11) SIGSEGV(重点:段错误信号) 12) SIGUSR2(用户自定义)13) SIGPIPE(重点:管道破裂)14) SIGALRM(重点:定时器,闹钟)15) SIGTERM(非强制关闭,kill的默认信号,可等紧急事件处理完后再关闭)
16) SIGSTKFLT 17) SIGCHLD(子进程消亡,给父进程发此信号。默认忽略)18) SIGCONT(继续)19) SIGSTOP(重点:强制暂停) 20) SIGTSTP(暂停).................
1~64;32应用编程。
如何响应:
Term Default action is to terminate the process. (关闭)
Ign Default action is to ignore the signal. (忽略:允许别人给我发,但不做响应)
wait
Core Default action is to terminate the process and dump core (see
core(5)). (内存转储:和Term类似,关闭生成一个core文件)
gdb a.out -c core (gdb直接停在出错位置)
Stop Default action is to stop the process.
Cont Default action is to continue the process if it is currently
stopped.
2. 信号的传递过程
kill -xx xxxx
发送进程 信号 接收进程
kill -9 1000
a.out 9 1000
2.1 发送端
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig); (给别人或自己发)
功能:通过该函数可以给pid进程发送信号为sig的系统信号。
参数:pid 要接收信号的进程pid
sig 当前程序要发送的信号编号 《=== kill -l
返回值:成功 0
失败 -1;
int raise(int sig)== kill(getpid(),int sig); (给自己发)
功能:给进程自己发送sig信号
unsigned int alarm(unsigned int seconds);SIGALAM alarm(5); 定时5秒后关闭
功能:定时,由系统给当前进程发送信号,默认功能为关闭a.out(调用alarm的进程) 类似于单片机中的中断;
也称为闹钟函数 (返回值:上一次闹钟还有多久到达,不常用)
闹钟只有一个,定时只有一次有效,
但是必须根据代码逻辑是否执行判断。
int pause(void);
功能:进程暂停,不再继续执行,除非收到其他信号。(信号:需要捕获才管用,直接调用kill无效) (调用后,默认为暂停功能)
(捕获CONTN后,pause()跳过,程序被唤醒继续执行)用3号退出pause状态也行
信号 kill -l ==>前32个有具体含义的信号
2.2 接收端
每个进程都会对信号作出默认响应,但不是唯一响应。
一般如下三种处理方式:
1、默认处理
2、忽略处理 (9,19,除外)
3、自定义处理 (也叫信号的捕获) (9,19不能被忽略和自定义, 捕获)
以上三种方式的处理需要在如下函数上实现。
信号注册函数原型:
void ( *signal(int signum, void (*handler)(int)) ) (int); (参数1:信号数或者信号名;参数2:要调用的函数名)
typedef void (*sighandler_t)(int);
===》void (*xx)(int); == void fun(int);
===》xx是 void fun(int) 类型函数的函数指针
===》typedef void(*xx)(int) sighandler_t; ///错误
typedef int myint;
===>sighandler_t signal(int signum, sighandler_t handler);
===> signal(int sig, sighandler_t fun);
===> signal(int sig, xxx fun);
===>fun 有三个宏表示:(SIG_DFL 表示收到信号,恢复默认处理;SIG_IGN 表示:收到信号,忽略处理; fun 表示自定义处理)
结论: 9 19 不能被忽略也不能被自定义
自定义信号处理:
1、必须事先定义自定义函数,必须是如下格式:
void fun(int sig) sig 接收到的信息编号 (fun:定义的函数名;sig:信号编号或信号名)
{
}
2、在所有的信号中有如下两个特列:
10 SIGUSR1
12 SIGUSR2
专门预留给程序员使用的未定义信号。
3.共享内存(SHM)
shm,sem,msg
system v : 共享内存(shm) 信号量集(sem) 消息队列(msg),发消息时,给消息设置等级,后发的可能先读,其余与管道类似
IPC对象操作通用框架:
0x ftok
key值 ==> 申请 ==》读写 ==》关闭 ==》卸载
key值:===》唯一键值
创建方式有三种:
1、IPC_PRIVATE 固定的私有键值,其值等于 0x0
一般用于有亲缘关系的进程间使用。
2、ftok()创建临时键值。
#include <sys/types.h>
#include <sys/ipc.h>
"/etc" '!'
key_t ftok(const char *pathname, int proj_id); (ftok:申请K值)
功能:通过该函数可以将pathname指定的路径用来以
proj_id生成唯一的临时键值。
参数:pathname 路径+名称===》任意文件,只要不会
被删除重建即可。
proj_id 整形的数字,一般用ASCII码的单字符 (如:!)
表示与参数1的运算。
返回值:成功 返回唯一键值
失败 -1;
3.共享内存相关的命令行命令:
1. ipcs -a 查询共享内存,信号量集,消息队列
2. ipcrm -s 删除信号量集
-m 删除共享内存 (用Id删除,M:)
共享内存 ===》效率最高的进程间通信方式
4.共享内存的操作流程:
key ==》申请对象 ==》映射对象==》读写对象
==》撤销映射 ==》删除对象
4.1 申请对象:shmget()
#include <sys/ipc.h>
#include <sys/shm.h>
ps aux|grep a.out
share memory get IPC_CREAT|0666
int shmget(key_t key, size_t size, int shmflg);
功能:使用唯一键值key向内核提出共享内存使用申请
参数:key 唯一键值
size 要申请的共享内存大小 (size大小,是页大小(4K)的整数倍)
shmflg 申请的共享内存访问权限,八进制表示
如果是第一个申请,则用IPC_CREAT
如果要检测是否存在,用IPC_EXCL
返回值:成功 返回共享内存id,一般用shmid表示
失败 -1;
share memory attach
4.2 映射对象:shmat()
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:将指定shmid对应的共享内存映射到本地内存。
参数:shmid 要映射的本地内存
shmaddr 本地可用的地址,如果不确定则用NULL,表示
由系统自动分配。
shmflg
0,表示读写
SHM_RDONLY,只读
返回值:成功 返回映射的地址,一般等于shmaddr
失败 (void*)-1 (不是NULL,NULL是(void*)0)
4.3 读写共享内存:类似堆区内存的直接读写:
char * p ;
write(fd,p,);
read(fd,p,1024);
memcpy(p,buf,1024);strcpy();
memset(p,0,1024);== bzero(p,1024);
memcmp(p,buf,1024); strcmp(a,b);
字符串: strcpy(p,"hello");
字符/数字: 直接赋值
1、共享内存数据的存储方式是拷贝还是剪切? 拷贝
2、共享内存的数据如果多次不同进程读写会怎么样?
同一操作对象,数据没有偏移情况下会覆盖。
4.4 撤销映射:shmdt (断开关联关系)
int shmdt(const void *shmaddr);
功能:将本地内存与共享内存断开映射关系。
参数:shmaddr 要断开的映射地址。
返回值:成功 0
失败 -1;
4.5 删除对象:shmctl (删除共享内存段)
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:修改共享内存属性,也可以删除指定的共享内存对象。
参数:shmid 要删除的共享内存对象
cmd IPC_RMID 删除对象的宏
buff NULL 表示只删除对象。
返回值:成功 0
失败 -1