进程间通信(单机)
IPC(InterProcess Communication)
IPC通信常有管道(无命名管道和命名管道),消息队列,信号量,共享存储,socket,stream等,socket,stream支持不同主机IPC
无名管道:半双工,只能用于父子,兄弟进程间,不属于文件系统,存在于内存中,可read,write
管道数据读走就没了
<unistd.h>
int pipe(int fd[2])
fd[0]读 fd[1]写
返回-1创建失败
管道编程实现
int fd[2]
if(pipe(fd)<0)
close(fd[0]);
write(fd[1],”hello”,strlen(“hello”));
close(fd[1])
read(fd[0],buf,128);
父进程开始第一行sleep(3)会让子进程先执行
父进程最后wait()会让子进程先结束
创建命名管道
FIFO,命名管道,是一种文件类型
可以在无关进程间交换数据
FIFO有路径名与之关联,以一种特殊设备文件形式存在于文件系统中
man 3 mkfifo
int mkfifo(“./file1”,0600)
已存在则错误,返回-1
<errno.h>
if(mkfifo(“./file”,0600)==-1) && errno!=EEXIST)
errno 是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义
命名管道数据通行编程实现
man 2 open
open FIFO文件file只读时阻塞到另一进程为写而打开它
只写打开时要阻塞到另一进城为读打开它
消息队列通信原理
消息队列是消息的链接表,存放在内核中,一个消息有一个标识符来标识
消息队列面向记录,有特定格式和优先级
消息队列独立于发送接收进程,进程终止消息队列内容不会删除
可实现消息随机查询,消息不一定以先进先出次序读取
消息队列相关api
man 2 msgget
int msgid=msgget(0x1234,IPC_CREAT|0700);
struct msgbuf
{
long mtype;
char mtext[128];
}
msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),888,0);
(4:值>0接收类型等于4的第一个消息,为0接收第一个消息,<0接收类型小于等于绝对值的消息)
msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);
sendbuf可以为任何类型结构体,但第一个字段必须为long型
4:(IPC_NOWAIT 消息队列已满时不等待立即返回,为0则等待)
键值生成及消息队列移除
key_t key=ftok(“.”, ‘z’)
系统建立IPC通讯时必须指定一个ID值,通常情况下ID值通过ftok获取
msgctl(msgid, IPC_RMID, NULL);
移除消息队列
ipcs -q 查看消息队列
与命名管道相比,消息队列的优势在于:
1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。
2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。
3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收
共享内存概述
<sys/ipc.h><sys/shm.h>
int shmid=shmget(key,1024*4, IPC_CREAT)(2以字节为单位)
得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符
错误返回-1
char *shmaddr=shmat(shmid, 0, 0)
把共享内存区对象映射到调用进程的地址空间
2指定共享内存出现在进程内存地址的什么位置,为0自动分配
3(SHM_RDONLY)只读模式,其他为读写模式
shmdt(shmaddr)
禁止本进程访问共享内存
shmctl(shmid, IPC_RMID, 0)
销毁共享内存(3为共享内存管理结构体)
ipcs -m 查看共享内存
ipcrm -m (shmid) 删除共享内存
信号概述
对Linux来说,信号是软中断。
kill -l查看信号
信号处理三种方法:忽略,捕捉,默认动作
Signal(9,SIG_IGN); //忽略信号
SIGKILL和SIGSTOP不可被忽略
<signal.h>
void handler(int signum)
{
printf(“%d”,signum);
}
signal(SIGINT,handler)
设置某一信号的对应动作,形参signum为signal传入的1(SIGINT)值
kill(pid, SIGKILL)
向进程1发送信号2(杀死进程)
man 7 signal
kill -9 PID 杀死进程
atoi(argv[1]) ASICII码转数字
sprintf(cmd, “kill -%d %d”);把格式化数据写入字符串缓冲区
alarm(uint seconds);到seconds秒后向进程发送SIGALARM信号
(默认终止该进程)
pause();挂起进程到收到信号为止
ctrl+\退出进程
信号携带消息编程
<signal.h>
struct sigaction act;
act.sa_sigaction=handler;
act.sa_flags=SA_SIGINFO;
sigaction(SIGUSR1, &act, NULL)
信号量概述
信号量在程序中起到的功能相当于房间的钥匙(信号量集,p操作:拿钥匙v操作:放回钥匙)本质为一个非负的整数计数器。
一次仅允许一个进程使用的资源称为临界资源,如打印机。