进程间通信
来源:互联网 发布:win10 装linux 编辑:程序博客网 时间:2024/06/05 07:38
1、管道方式
1)无名管道:(只能在有亲缘关系的进程间进行通信)
#include<stdio.h>#include<unistd.h>int main(){ int fd[2]; if(pipe(fd)<0){ printf("创建管道失败\n"); return -1; } // fd[0] 用于输入 // fd[1] 用于输出 int pid = fork(); // 创建一个子进程 if(pid<0){ printf("创建子进程失败\n"); return -1; } else if(pid==0){ // 子进程中 write(fd[1], "hello", sizeof("hello")); } else { // 父进程中 char msg[8]; read(fd[0], msg, sizeof(msg)-1); printf("父进程收到消息:%s\n", msg); } return 0;}
2)有名管道(如果知道管道名称,可以支持在不同进程中的通信)
创建、写
#include<stdio.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>int main(){ const char *fifo_name = "./hchlqlz"; if(access(fifo_name, F_OK)==-1){ // 判断该管道是否存在 // access函数用于判断当前用户对文件的权限,功能取决于第二个参数 // R_OK, W_OK, X_OK ,是否可读, 可写, 可执行 // F_OK,文件是否存在 if(mkfifo(fifo_name, 0666)==-1){ printf("创建管道失败\n"); return -1; } } int fid = open(fifo_name, O_WRONLY); // 以只写的方式打开文件 write(fid, "hello", sizeof("hello")); close(fid); return 0;}
读
#include<stdio.h>#include<fcntl.h>#include<unistd.h>int main(){ const char *fifo_name = "./hchlqlz"; int fid = open(fifo_name, O_RDONLY); char msg[8]; read(fid, msg, sizeof(msg)-1); close(fid); printf("%s\n", msg); return 0;}
注:打开管道时必须同时有读数据进程和写数据进程,缺了某一个,就会阻塞。
2、信号(signal)
#include<stdio.h>#include<unistd.h>#include<signal.h>bool ing = true;void stop(int sig){ // sig:收到的信号 ing = false;}int main(){ signal(2, stop); // 将信号2与stop函数绑定,如果接收到信号2,则调用stop函数 while(ing){ printf("!"); fflush(NULL); // 刷新缓冲区 sleep(1); // 休眠1s } printf("结束运行\n"); return 0;}
3、消息队列
主要函数:
1)int msgget(key_t, key, int msgflg)
key:消息队列的key
msgflg:权限,可以异或IPC_CREAT、IPC_EXCL(如果不存在该消息队列,返回-1)
2)int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg)
msgid:消息队列id
msg_ptr:指向一个消息的指针,消息结构需要以一个long 作为开始,可以附加其他的信息
msg_sz:消息大小
msgflg:当队列满时进行的操作,0为阻塞,IPC_NOWAIT返回-1
3)int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg)
msgtype:指定获取的消息,0:获取队列第一条消息,>0:获取指定类型的第一条消息,<0:获取类型<=msgtype绝对值的第一条消息
4)int msgctl(int msgid, int command, struct msgid_ds *buf)
command:执行的操作,IPC_RMID删除消息队列,IPC_STAT,设置buf,IPC_SET,用buf 设置消息队列的关联值
#include<stdio.h>#include<string.h>#include<sys/msg.h>struct MSG{ long type; char msg[128];};int main(){ int qid = msgget(1, 0666 | IPC_CREAT); if(qid==-1){ printf("获取消息队列失败\n"); return -1; } MSG s1; s1.type = 1; strcpy(s1.msg, "hello1"); msgsnd(qid, &s1, sizeof(s1), 0); MSG s2; s2.type = 3; strcpy(s2.msg, "hello3"); msgsnd(qid, &s2, sizeof(s2), 0); MSG s3; msgrcv(qid, &s3, sizeof(s3), 3, 0); printf("从消息队列中取到的消息是:%s\n", s3.msg); msgctl(qid, IPC_RMID, 0); return 0;}
4、共享内存
1)int shmget(key_t key, size_t size, int shmflg)
比消息队列的msgget多了一个size表示共享内存的大小。
2)void *shmat(int shm_id, const void *shm_addr, int shmflg)
刚获取到的共享内存,不能立即投入使用,需要用shmat函数来启动对该共享内存的访问,把共享内存连接到当前进程的地址空间上。
id:标识
addr:连接到当前进程的地址位置,为NULL时由系统进行选择
3)int shmdt(const void *shmaddr)
分离共享内存。
4)int shmctl(int shm_id, int command, struct shmid_ds *buf)
对共享内存进行操控。和消息队列类似
创建并写
#include<stdio.h>#include<string.h>#include<sys/shm.h>struct Student{ char name[16]; char note[128];};int main(){ int sid = shmget(520, sizeof(Student), 0666|IPC_CREAT); void *addr = shmat(sid, NULL, 0); Student* stu = (Student *)addr; strcpy(stu->name, "hchlqlz"); strcpy(stu->note, "AC是我的梦想"); shmdt(addr); return 0;}
读并删除
#include<stdio.h>#include<sys/shm.h>struct Student{ char name[16]; char note[128];};int main(){ int sid = shmget(520, sizeof(Student), 0666); void* addr = shmat(sid, NULL, 0); Student* stu = (Student*) addr; printf("学生姓名:%s\n", stu->name); printf("学生备注:%s\n", stu->note); shmdt(addr); shmctl(sid, IPC_RMID, 0); return 0;}
- 进程&进程间通信
- 信号通信(进程间通信)
- 进程间通信-管道通信
- 进程间通信--管道通信
- [进程通信] 进程间通信 之 管道
- 进程与进程间通信
- 【IO进程】进程间通信
- 进程间通信
- 进程间通信方式
- 进程间通信IPC
- 进程间通信
- 操作系统:进程间通信
- 进程间的通信
- 进程间通信
- 进程间通信IPC
- 进程间通信
- 进程间通信总结
- 进程间管道通信
- mongoDB备份和恢复
- Num.3 递归算法
- 回文串编程
- 基本使用方法之二
- Oracle 学习笔记
- 进程间通信
- Java四种引用类型
- 管管我吧,我很听你的话
- BigDecimal中的精度问题
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B
- TCP和Socket关系
- JS技术(4)---定义对象,添加函数,改变对象属性
- Golang学习笔记
- vmware + redhat6.6+ g++的安装