进程间通信之信号:
信号 -- 软中断
中断
信号 --- 中断源
中断(信号)处理程序 --- 负责对该中断(信号)做出反应的
//信号处理函数 的注册函数
#include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:
给signum信号设置一个信号处理函数
参数:
@signum 要处理的信号
@handler 信号处理函数
返回值:
成功 将返回上一次的信号处理函数的地址
失败 SIG_ERR (void (*sighandler_t)(int) 类型的 -1)
void sighandler (int signo) //信号处理函数
{
}
//signo //参数 ---表示 接收到的信号的编号
SIGKILL
SIGSTOP //不能阻塞,不能处理,不能忽略
#include
#include
#include
typedef void (*sighandler_t)(int);
void sighandler(int signo)
{
printf("signo = %d\n",signo);
}
int main(int argc, const char *argv[])
{
//signal(SIGINT,SIG_IGN);
sighandler_t ret = signal(SIGINT,sighandler);
printf("ret = %p\n",ret);
printf("ret = %p\n",SIG_IGN);
while(1)
{
printf("hello \n");
sleep(1);
}
//signal(SIGINT,ret);
return 0;
}
1、发送端
#include
#include
int kill(pid_t pid, int sig);
功能:通过该函数可以给pid进程发送信号为sig的系统信号。
参数:pid 要接收信号的进程pid
sig 当前程序要发送的信号编号 《=== kill -l
返回值:成功 0
失败 -1;
练习:
编写一个自己的kill程序,尽量模拟kill命令的效果。
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
pid_t pid = atoi(argv[1]);
int i = 0;
for(i = 1;i<32;++i)
{
printf("i =%d\n",i);
if(kill(pid,i)<0)
{
perror("kill fail");
return -1;
}
}
return 0;
}
unsigned int alarm(unsigned int seconds);SIGALAM
功能:定时由系统给当前进程发送信号
也称为闹钟函数
闹钟只有一个,定时只有一次有效,
但是必须根据代码逻辑是否执行判断。
int pause(void);
功能:
进程暂停,不再继续执行,除非
收到其他信号。
练习:
检测用户是否输入,
如果用户3s没有输入,
则超时一次,
如果超时3次自动退出
#include
#include
#include
#include
#include
int cnt = 0;
void sighandler(int signo)
{
alarm(3);
cnt++;
printf("cnt=%d\n",cnt);
if(cnt==3)
{
exit(0);
}
}
int main(int argc, const char *argv[])
{
alarm(3);
char buf[1024];
signal(SIGALRM,sighandler);
while(1)
{
fgets(buf,sizeof(buf),stdin);
printf("buf = %s\n",buf);
alarm(3);
cnt = 0;
}
return 0;
}
传统的进程间通信方式:
1.无名管道
2.有名管道
3.信号
Sys V 系统v的IPC对象:
1.共享内存 (*) --- 效率最高的通信方式
2.消息队列 //--- 系统提供一种消息队列的通信机制
3.信号量集 //--- 信号量集(集合)---很多个信号量
//互斥 和 同步
共享内存:
是一块内核中保留的物理内存空间
/IPC对象共享内存:
1.ftok
ftok()创建临时键值。
#include
#include
"/etc" '!'
key_t ftok(const char *pathname, int proj_id);
功能:通过该函数可以将pathname指定的路径用来以
proj_id生成唯一的临时键值。
参数:pathname 路径+名称===》任意文件,只要不会
被删除重建即可。
proj_id 整形的数字,一般用ASCII码的单字符
表示与参数1的运算。
返回值:成功 返回唯一键值
失败 -1;
2.shmget //获取IPC对象
// shared memory
1、IPC_PRIVATE 固定的私有键值,其值等于 0x0
一般用于有亲缘关系的进程间使用。
1、申请对象:shmget()
#include
#include
ps aux|grep a.out
shared memory get IPC_CREAT|0666
int shmget(key_t key, size_t size, int shmflg);
功能:
使用唯一键值key向内核提出共享内存使用申请
参数:key 唯一键值
size 要申请的共享内存大小
shmflg 申请的共享内存访问权限,八进制表示
如果是第一个申请,则用IPC_CREAT
如果要检测是否存在,用IPC_EXCL
返回值:
成功 返回共享内存id,一般用shmid表示
失败 -1;
share memory attach
key --- IPC_PRIVATE //创建一个key对应ipc对象 ---- 主要用于亲缘关系进程间
key --- 不是IPC_PRIVATE
shmflag 指定 IPC_CREAT|0666 //此时如果ipc对象不存在,则创建
ipcs -a 查询共享内存,信号量集,消息队列
ipcrm -s 删除信号量集
-m 删除共享内存
3.建立映射
shmat
映射对象:shmat()
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:将指定shmid对应的共享内存映射到本地内存。
参数:shmid 要映射的本地内存
shmaddr 本地可用的地址,如果不确定则用NULL,表示
由系统自动分配。
shmflg
0 , 表示读写
SHM_RDONLY, 只读
返回值:
成功 返回映射的地址,一般等于shmaddr
失败 (void*)-1
4. 撤销映射:shmdt
int shmdt(const void *shmaddr);
功能:将本地内存与共享内存断开映射关系。
参数:shmaddr 要断开的映射地址。
返回值:成功 0
失败 -1;
5. 删除对象:shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
修改共享内存属性,也可以删除指定的共享内存对象。
参数:shmid 要删除的共享内存对象
cmd
IPC_RMID 删除对象的宏
buff NULL 表示只删除对象。
返回值:成功 0
失败 -1
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
//1.key
key_t key = ftok("/",'B');
if(key<0)
{
perror("fork fail");
return -1;
}
printf("key is %#x\n",key);
//2.shmid
int shmid = shmget(key,1024,IPC_CREAT|0666);
if(shmid<0)
{
perror("shmget fail");
return -1;
}
printf("shmid = %d\n",shmid);
//shmat
void *p = shmat(shmid,NULL,0);
if(p==NULL)
{
perror("shmat fail");
return -1;
}
int i = 0;
while(i < 10)
{
*(int*)p = 100;
i++;
printf("i = %d\n",i);
sleep(1);
}
//shmdt
if(shmdt(p)<0)
{
perror("shmdt fail");
return -1;
}
//5.shmctl
if(shmctl(shmid,IPC_RMID,NULL)<0)
{
perror("shmctl fail");
return -1;
}
return 0;
}
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
//1.key
key_t key = ftok("/",'B');
if(key<0)
{
perror("fork fail");
return -1;
}
printf("key is %#x\n",key);
//2.shmid
int shmid = shmget(key,1024,IPC_CREAT|0666);
if(shmid<0)
{
perror("shmget fail");
return -1;
}
printf("shmid = %d\n",shmid);
//shmat
void *p = shmat(shmid,NULL,0);
if(p==NULL)
{
perror("shmat fail");
return -1;
}
printf("%d\n",*(int *)p);
//shmdt
if(shmdt(p)<0)
{
perror("shmdt fail");
return -1;
}
//5.shmctl
if(shmctl(shmid,IPC_RMID,NULL)<0)
{
perror("shmctl fail");
return -1;
}
return 0;
}
kill(pid,SIGUSR1)
pause
#include
#include
#include
typedef void (*sighandler_t)(int);
void sighandler(int signo)
{
printf("signo = %d\n",signo);
}
int main(int argc, const char *argv[])
{
sighandler_t ret = signal(SIGINT,sighandler);
while(1)
{
printf("hello \n");
pause();
}
//signal(SIGINT,ret);
return 0;
}