赞
踩
1、通常来说进程间的通信方式共有六种:
(1)管道通信 ——无名管道 (pipe)、有名管道 (fifo)
(2)信号通信 (sinal)
(3)信号量 (Semaphore)
(4)共享内存 (SharedMemory)
(5)消息队列 (MessageQueue)
(6)套接字 (Socket)
但是本文只介绍前五种,你肯定疑惑了,第六种为什么不说?
那原因也很简单,我觉得文章太长了!
1、无名管道的特点:
(1)只能用于具有亲缘关系的进程之间的通信
(2)是一个单工的通信模式,具有固定的读端和写端
(3)管道也可以看成一种特殊文件,对他的读写可以使用read(),write()函数
2、原理示意图:
3、pipe函数
功能:创建无名管道
头文件: #include<unistd.h> 函数原型: int pipe(int fd[]); 参数: fd[]:包含两个元素的整型数组,存放读端和写端的文件描述符 例子: #include <stdio.h> #include <unistd.h> int main() { int fd[2]; pipe(fd); //传出两个文件描述符 fd[0] fd[1] int pid = fork(); if(pid == 0)//子进程 { close(fd[0]); //子进程关闭读端 write(fd[1], "hello", sizeof("hello")); } else if(pid > 0)//父进程 { char buf[100] = { 0 }; close(fd[1]);//父进程关闭写端 wait(NULL);//等待子进程结束 read(fd[0], buf, sizeof(buf));//读出数据 printf("read is %s\n", buf);//打印 } }
1、有名管道的特点:
(1)可以使两个不相关的进程实现彼此通讯
(2)该管道可以通过路径名指出,在文件系统中可见
(3)严格遵守先进先出的规则,在开始处读数据,末尾处写数据
2、原理示意图:
3、mkfifo函数
功能:创建有名管道
头文件: #include<sys/types.h> #include<sys/state.h> 函数原型: int mkfifo(const char *filename,mode_t mode); 参数: filename:要创建的管道名 mode:管道的访问权限 例子: //读端 #include <stdio.h> #include <unistd.h> #include <fcntl.h> int main() { mkfifo("myfifo", 0666); int fd = open("myfifo", O_RDWR); if(fd > 0) { char buf[100] = { 0 }; read(fd, buf, sizeof(buf)); printf("read is %s\n", buf); close(fd); } } //写端 #include <stdio.h> #include <unistd.h> #include <fcntl.h> int main() { int fd = open("myfifo", O_RDWR); if(fd > 0) { write(fd, "hello", sizeof("hello")); close(fd); } }
1、信号是进程间通信机制中唯一的异步通讯机制
2、进程可以通过三种方式来响应信号
(1)忽略信号:对信号不做如何处理
(2)捕捉信号:定义信号处理函数,信号发生时,执行相应的处理函数
(3)执行默认操作:常见的信号如下
· SIGHUP:从终端上发出的结束信号。
· SIGINT:来自键盘的中断信号,即Ctrl+c。
· SIGKILL:该信号结束接收信号的进程。
· SIGCHLD:标识子进程停止或结束的信号。
· SIGSTOP:来自键盘Ctrl+z,或调试程序的停止执行信号。
· SIGQUIT:来自键盘的退出信号,即Ctrl+\。
· SIGALARM:进程的定时器到期,发送该信号。
3、kill函数
功能:发送信号给进程
头文件:
#include<signal.h>
#include<sys/types.h>
函数原型:
int kill(pid_t pid,int sig);
参数:
pid:发送信号给进程号为pid的进程
sig:信号类型
例子:
#include <signal.h>
int main()
{
kill(11111, SIGINT);
}
4、signal函数
功能:定义一个函数,当产生某个信号时,自动执行此函数
头文件: #include<signal.h> 函数原型: typedef void (*sighandler_t)(int); sighandler_t signal(int signum,sighandler_t handler); 参数: signum:指定信号代码 handler:SIG_IGN 忽略该信号 SIG_DFL 采用系统默认方式处理信号 自定义的信号处理函数 例子: #include <signal.h> #include <stdio.h> #include <stdlib.h> void *fun(int n) //n 当产生某个信号时,信号值 { printf("recv a signal CTRL+C %d\n", n); exit(0); } int main() { signal(SIGINT, fun); while(1); //不让程序结束 }
5、alarm函数
功能:在进程中设定一个定时器,当定时器时间到了,发送一个SIGALARM信号给进程
头文件: #include<unistd.h> 函数原型: unsigned int alarm(unsigned int seconds); 参数: seconds:指定秒数 例子: //发送信号 #include <stdio.h> int main() { alarm(2); while(1) { printf("hello world\n"); sleep(1); } } //接收信号 #include <stdio.h> #include <signal.h> void fun(int n) { printf("recv a signal SIGALRM\n"); } int main() { alarm(1); //1秒钟之后产生SIGALRM信号 signal(SIGALARM, fun); //捕获SIGALRM信号,执行fun while(1); //不让程序暂停 }
那个,这个暂时先放一放。
1、共享内存是一种最为高效的进程间通信方式:因为进程可以直接读写内存,不需要任何数据的复制
2、原理图:
3、shmget函数
功能:创建共享内存
头文件: #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> 函数原型: int shmget(key_t key,int size,int shmflg); 参数: key:共享内存的键值 size:共享内存区的大小 shmflg:共享内存的权限,可以使用八进制表示法 返回值: 共享内存的标识符 例子: #include <sys/shm.h> #include <stdio.h> int main() { int shmid = shmget(55555, 10 * sizeof(int), 0666 | IPC_CREAT);//IPC_CREAT不存在就新建 printf("shmid is %d\n", shmid); }
4、shmat函数
功能:映射共享内存
头文件:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
函数原型:
char *shmat(int shmid,const void *shmaddr,int shmflg);
参数:
shmid:要映射的共享内存区标识符
shmaddr:将共享内存映射到指定地址(若为0,表示系统自动分配地址,并把该段共享内存映射到调用进程的地址空间)
shmflg:共享内存的权限,可以使用八进制表示法
返回值:
被映射的段地址
例子:
int *p = shmat(shmid, NULL, 0);
5、shmdt函数
功能:撤销映射
头文件: #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> 函数原型: int shmdt(const void *shmaddr); 参数: shmaddr:被映射的共享内存段地址 例子: #include <sys/shm.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> int main() { int shmid = shmget(IPC_PRIVATE, 10 * sizeof(int), 0644); printf("shmid %d\n", shmid); int i; int pid = fork(); //创建子进程 if(pid == 0) //子进程在运行 { //写共享内存 int *p = shmat(shmid, NULL, 0); //映射 for(i = 0; i < 10; i++) { p[i] = i; //写入共享内存 } shmdt(p); //解除映射 exit(0); //子进程结束 } else if(pid > 0) { //读共享内存 wait(NULL); //等子进程结束 int *p = shmat(shmid, NULL, 0); //映射 for(i = 0; i < 10; i++) { printf("%d\n", p[i]); //读出 } shmdt(p); //解除映射 } }
1、消息队列就是一些消息的列表,可以实现消息的随机查询,这些消息存在于内核中,有队列ID来标识。
2、msgget函数
功能:
头文件:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
函数原型:
int msgget(key_t key,int msgflg);
参数:
key:消息队列的键值
msgflg:权限标志位
返回值:
消息队列ID
3、msgsnd函数
功能:
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> 函数原型: int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg); 参数: msqid:消息队列的队列ID msgp:指向消息结构的指针 struct msgbuf { long mtype;//消息类型 char mtext[100];//消息正文 } msgsz:消息正文的字节数 msgflg:IPC_NOWAIT 消息无法发送函数立即返回 0 调用阻塞直到发送成功
4、msgrcv函数
功能:
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> 函数原型: int msgrcv(int msqid,const void *msgp,size_t msgsz,long int msgtyp,int msgflg); 参数: msqid:消息队列的队列ID msgp:消息缓冲区 struct msgbuf { long mtype;//消息类型 char mtext[100];//消息正文 } msgsz:消息正文的字节数 msgtyp:0 接收消息队列第一个消息 大于0 接收消息队列第一个类型为msgtyp的消息 小于0 接收消息队列中第一个类型值不小于msgtyp绝对值且类型值又最小的消息 msgflg:IPC_NOWAIT 若消息队列没有对应类型的消息,函数立即返回 0 调用阻塞直到接收成功
5、msgctl函数
功能:删除队列消息
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
函数原型:
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
参数:
msqid:消息队列的队列ID
cmd:IPC_RMID 从系统内核中删除消息队列
buf:通常为NULL
6、例子
//发送消息 #include <sys/msg.h> #include <stdio.h> #include <string.h> struct msgbuf { long mtype; char mtext[100]; }; int main(int argc, char *argv[]) { if(argc < 3) { printf("param error, like this: ./send 1 hello\n"); return -1; } struct msgbuf a; a.mtype = atoi(argv[1]);//接收消息类型 strcpy(a.mtext, argv[2]);//接收消息正文 int msgid = msgget(11111, 0666 | IPC_CREAT);//创建消息队列 msgsnd(msgid, &a, sizeof(a) - sizeof(long), 0);//发送消息 } //接收消息 #include <sys/msg.h> #include <sys/ipc.h> #include <stdio.h> struct msgbuf { long mtype; char mtext[100]; }; int main(int argc, char *argv[]) { struct msgbuf b;//定义结构体变量 if(argc < 2) { printf("param error, like this: ./recv 1\n"); } int msgid = msgget(11111, 0666 | IPC_CREAT);//创建消息队列 msgrcv(msgid, &b, sizeof(b) - sizeof(long), atoi(argv[1]), 0);//接收消息正文 printf("msg type is %lu, buf is %s\n", b.mtype, b.mtext);//打印 }
总结不动了!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。