赞
踩
文章目录
进程间通信(IPC,InterProcess Communication)是指在不同的进程之间传播或交换信息。
前7种IPC通常限于同一台主机的各个进程间的IPC。然而套接字和STREAMS,是仅有的两种支持不同主机上各个进程间IPC的类型。
管道是UNIX系统IPC的最古老形式,并且所有UNIX系统都提供此种通信机制。
管道的特点(也是两种局限性):
经由参数filedes返回两个文件描述符:filedes[0]为读而打开,filedes[1]为写而打开。filedes[1]的输出是filedes[0]的输人。
调用fork之后做什么取决于我们想要有的数据流的方向。对于从父进程到子进程的管道,父进程关闭管道的读端(fd[0]),子进程则关闭写端(fd[1])。图15-3显示了在此之后描述符的安排。
为了构造从子进程到父进程的管道,父进程关闭fd[1](写端),子进程关闭fd[0](读端)。 记忆:通常喜欢念0 1对应这里的 读 写。
3.例子:
数据流从父进程流入子进程,父进程打开写端,关闭读端。子进程则是打开读端,关闭写端。反之,如果数据流从子进程流向父进程也是一样。
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
-
- int main()
- {
- int fd[2];
- int pid;
- char buf[128];
-
- // int pipe(int pipefd[2]);
-
- if(pipe(fd) == -1){
- printf("creat pipe failed\n");
- }
- pid = fork();
-
- if(pid<0){
- printf("creat child failed\n");
- }
- else if(pid > 0){
- sleep(3);
- printf("this is father\n");
-
- close(fd[0]);
- write(fd[1],"hello from father",strlen("hello form father"));
- wait();
- }else{
- printf("this is child\n");
- close(fd[1]);
- read(fd[0],buf,128);
- printf("read from father: %s\n",buf);
- exit(0);
- }
-
- return 0;
- }
运行效果:
一旦已经用mkfifo创建了一个FIFO,就可用open打开它。其实,一般的文件I/O函数(close、read、write、unlink等)都可用于FIFO。
FIFO的通信方式类似于在进程中使用文件来传输数据,只不过FIFO类型文件同时具有管道的特性。在数据读出时,FIFO管道中同时清楚数据,并且”先进先出“。
3. FIFO有下面两种用途;
(1) FIFO由shell命令使用以便将数据从一条管道线传送到另一条,为此无需创建中间临时文件。
(2) FIFO用于客户进程-服务器进程应用程序中,以在客户进程和服务器进程之间传递数据。我们各用一个例子来说明这两种用途。
代码段:
先运行 read.c,再运行 write.c ;运行之后读端先阻塞起来等待写端的写入,写入完之后读端开始运行。
读端代码块:
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <errno.h>
- #include <fcntl.h>
-
- //int mkfifo(const char *pathname, mode_t mode);
- int main()
- {
- char buf[30] = {0};
- int nread = 0;
-
-
- if( (mkfifo("./file",0600) == -1) && errno!=EEXIST){
- printf("mkfifo failuer\n");
- perror("why");
- }
-
- int fd = open("./file",O_RDONLY);
- printf("open success\n");
-
- while(1){
- nread = read(fd,buf,30);
- printf("read %d byte from fifo,context:%s\n",nread,buf);
- }
- close(fd);
- return 0;
- }
写端代码块:
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <string.h>
-
- //int mkfifo(const char *pathname, mode_t mode);
- int main()
- {
- int cnt = 0;
- char *str = "message from fifo";
-
- int fd = open("./file",O_WRONLY);
- printf("write open success\n");
-
- while(1){
-
- write(fd, str, strlen(str));
- sleep(1);
- if(cnt == 5){
- break;
- }
- }
- close(fd);
- return 0;
- }
消息队列是消息的链接表存放在内核中并由消息队列标识符标识。
2.1 特点:
2.2 函数原型:
从队列中取消息,并不一定要以先进先出次序,也可以按信息的类型字段取消息。
函数msgget中key值很关键,相当于一个索引。进程通过这个键值,在Linux内核中找到相应的队列(确保了队列是同一个) 在以下两种情况中,msgget 将创建一个新的消息队列:
函数msgrcv在读取消息队列时,type参数有下面几种情况:
代码端:
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #include <string.h>
- // int msgget(key_t key, int msgflg);
- // int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- // ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
- // int msgflg);
- struct msgbuf {
- long mtype; /* message type, must be > 0 */
- char mtext[256]; /* message data */
- };
-
- int main()
- {
- //1.huoqu
- struct msgbuf readBuf;
-
- //获取key值
- key_t key;
- key = ftok(".",'m');// “.” 表示当前路径,第二个参数随意,可以是数字,可以是字符
- printf("key=%x\n",key);
- // 获取/创建消息队列
- int msgId = msgget(key, IPC_CREAT|0777);//0777 可读可写可执行
- if(msgId == -1 ){
- printf("get que failuer\n");
- }
- memset(&readBuf,0,sizeof(struct msgbuf));
- //接收数据
- msgrcv(msgId, &readBuf,sizeof(readBuf.mtext),888,0); //第三个参数:消息类型,第四个参数:0 的意思是默认的方式接收消息,接收不到消息会一直阻塞
- printf("read from que:%s\n",readBuf.mtext);
- //发送数据
- struct msgbuf sendBuf = {988,"thank you for reach"};
- msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);
- //关闭数据
- msgctl(msgId,IPC_RMID,NULL);//第三个参数,通常设置为NULL
-
- return 0;
- }
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #include <string.h>
- // int msgget(key_t key, int msgflg);
- // int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- // ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
- // int msgflg);
- struct msgbuf {
- long mtype; /* message type, must be > 0 */
- char mtext[256]; /* message data */
- };
-
- int main()
- {
- //1.huoqu
- struct msgbuf sendBuf = {888,"this is message from quen"}; //第一个参数:消息的类型
- struct msgbuf readBuf;
-
- memset(&readBuf,0,sizeof(struct msgbuf));
- //获取key值
- key_t key;
- key = ftok(".",'m');// “.” 表示当前路径
- printf("key=%x\n",key);
- //创建消息队列
- int msgId = msgget(key, IPC_CREAT|0777);//0777 可读可写可执行
-
- if(msgId == -1 ){
- printf("get que failuer\n");
- }
- //发送数据
- msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);
- printf("send over\n");
- //接收数据
- msgrcv(msgId, &readBuf,sizeof(readBuf.mtext),988,0);//第四个参数:0 的意思是默认的方式接收消息,接收不到消息会一直阻塞
- printf("reaturn from get:%s\n",readBuf.mtext);
- //关闭消息队列
- msgctl(msgId,IPC_RMID,NULL);
-
- return 0;
- }
运行效果:
共享存储允许两个或更多进程共享给定的存储区。因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC。
2. 函数原型
- //创建或获取一个共享内存:成功返回共享内存ID,失败返回 -1
- int shmget(key_t key, size_t size, int shmflg);
- //连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回 -1
- void *shmat(int shmid, const void *shmaddr, int shmflg);
- //断开与共享内存的连接:成功返回0,失败返回 -1
- int shmdt(const void *shmaddr);
- //控制共享内存的相关信息:成功返回0,失败返回 -1
- int shmctl(int shmid, int cmd, struct shmid_ds *buf);
部分参数解释
代码段:
编程思路:
shm_write
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- //int shmget(key_t key, size_t size, int shmflg);
- int main()
- {
- int shmid;
- char *shmaddr;
-
- key_t key;
- key = ftok(".",1);
-
- shmid = shmget(key,1024*4,IPC_CREAT|0666);
- if(shmid == -1){
- printf("shmget noOk\n");
- exit(-1);
- }
- shmaddr = shmat(shmid,0,0);
-
- printf("shmat ok\n");
- strcpy(shmaddr,"chenlichen");
-
- sleep(5);
- shmdt(shmaddr);
- shmctl(shmid, IPC_RMID, 0);
-
- printf("quit\n");
- return 0;
- }
shm_get
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- //int shmget(key_t key, size_t size, int shmflg);
- int main()
- {
- int shmid;
- char *shmaddr;
-
- key_t key;
- key = ftok(".",1);
-
- shmid = shmget(key,1024*4,0);
- if(shmid == -1){
- printf("shmget noOk\n");
- exit(-1);
- }
- shmaddr = shmat(shmid,0,0);
-
- printf("shmat ok\n");
- printf("data: %s\n:",shmaddr);
-
- shmdt(shmaddr);
-
- printf("quit\n");
- return 0;
- }
运行效果:
前3种通信方式概况图:
2.Linux——信号_单片机爱好者之家的博客-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。