Linux 进程间通信(一)
Linux 进程间通信
进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源。但是,进程不是孤立的,不同的进程之间需要信息的交换以及状态的传递,因此需要进程间数据传递、同步与异步的机制。
分类
- 统一主机间进程通信
- Unix进程间通信方式
- 无名通道
- 有名通道
- 信号
- System V进程间通信方式
- 信号量
- 消息队列
- 共享内存
- Unix进程间通信方式
- 不同主机间进程通信
-
- RPC
- Socket
-
消息队列IPC
简单介绍下,所有相关的API函数:
API函数 | 用途 |
msgget | 创建一个新的消息队列 |
获取消息队列ID | |
msgsnd | 向消息队列发送消息 |
msgrcv | 从消息队列接受消息 |
msgctl | 获得消息队列的信息 |
设置消息队列的信息 | |
删除消息队列 |
函数原型如下:
// 函数原型 #include <sys/msg.h> int msgget( key_t key, int msgflag); /* key为消息队列的描述符 msgflag是一个设置选项,可以设置权限 返回值为消息队列ID */ int msgctl( int msgid, int cmd, struct msqid_ds *buf); /* msgid是msgget的返回值 cmd :IPC_STAT 获取消息队列当前的状态信息,保存到buf指向的空间 IPC_SET 设置消息队列的属性 IPC_RMID 从内核中删除msgid标识的消息队列 */ int msgsnd( int msgid, struct msgbuf *msgp, size_t msgsz, int msgflag); /* msgid为消息队列ID msgbuf 指向要发送的消息 msgsize 消息的大小 msgflag 操作标志位 */ int msgrcv(int msgid, struct msgbuf *msgbuf, size_t msgsize, long int msgtype, int msgflag); /* msgtype用来指定要接收的消息,分三种情况: 等于 0 返回消息队列中的第一个消息 大于0 返回消息队列中类型为msgtype的第一个消息 小于0 返回消息队列中类型值小于等于msgtype绝对值的消息中类型值最小的第一条消息 */
例子:

1 #include <stdio.h> 2 #include <sys/msg.h> 3 #include <sys/types.h> 4 #include <sys/ipc.h> 5 6 int main() 7 { 8 int msgid; 9 10 //通过这样可以避免标识符的重复 11 //key_t myKey; 12 //myKey = ftok("/home/queues/myqueue", 0); 13 14 msgid = msgget( 0x111, IPC_CREAT|0666); 15 if(msgid >= 0) 16 printf("Created a Msg Queue %d\n", msgid); 17 18 return 0; 19 } 20 21 创建消息队列

1 #include <stdio.h> 2 #include <sys/msg.h> 3 #include <sys/types.h> 4 5 int main(int argc, char **argv) 6 { 7 int msgid, ret; 8 struct msqid_ds buf; 9 10 //获取消息队列 11 msgid = msgget(0x111, 0); 12 13 if(msgid >= 0){ 14 ret = msgctl(msgid, IPC_STAT, &buf); 15 buf.msg_qbytes = 4096; 16 17 ret = msgctl(msgid, IPC_SET, &buf); 18 19 if(ret == 0){ 20 printf("change queue size success"); 21 } 22 } 23 24 return 0; 25 }

1 #include <stdio.h> 2 #include <sys/msg.h> 3 #include <sys/types.h> 4 #include <string.h> 5 6 typedef struct{ 7 long type; 8 float fval; 9 unsigned int unival; 10 char message[1024]; 11 }myType; 12 13 int main() 14 { 15 myType msg; 16 int qid,ret; 17 18 qid = msgget(0x111, 0); 19 if(qid > 0){ 20 msg.type = 1L; 21 msg.fval = 123.456; 22 msg.unival = 256; 23 strcpy( msg.message, "this is a msg in queue\n"); 24 25 ret = msgsnd(qid, (struct msgbuf*)&msg, sizeof(myType), 0); 26 if(ret != -1) 27 printf("sent success!\n"); 28 } 29 30 return 0; 31 }

1 #include <stdio.h> 2 #include <sys/msg.h> 3 #include <sys/types.h> 4 #include <string.h> 5 6 typedef struct{ 7 long type; 8 float fval; 9 unsigned int unival; 10 char message[1024]; 11 }myType; 12 13 int main() 14 { 15 myType msg; 16 int qid,ret; 17 18 qid = msgget(0x111, 0); 19 if(qid >= 0){ 20 21 ret = msgsnd(qid, (struct msgbuf*)&msg, sizeof(myType), 0); 22 if(ret != -1) 23 printf("recv success!\n"); 24 printf("type : %ld\n", msg.type); 25 printf("float value: %f\n", msg.fval); 26 printf("Unit value: %d\n", msg.unival); 27 printf("String value: %s\n", msg.message); 28 } 29 30 return 0; 31 }
共享内存
使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间的一次复制,当另外一个进程要从消息队列中读取消息时,又要进行一次从内核空间向用户空间的一次复制。而共享内存的优点就是完全省去了这些复制操作。
简单介绍下API函数:
API函数 | 用途 |
shmget | 创建一个新的共享内存区段 |
取得一个已经创建的共享内存区段的描述符 | |
shmctl | 取得一个共享内存区段的信息 |
为一个共享内存区段设置特定的信息 | |
删除一个共享内存区段 | |
shmat | 挂接一个共享内存区段 |
shmdt | 与一个共享内存区段分离 |
函数原型如下:
//函数原型 #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> int shmget( key_t key, size_t size, int shmflag ); /* key为描述符 size为共享内存区段的大小 shmflag为指令和权限设置 */ int shmctl( int shmid, int cmd, struct shmid_ds *buf ); /* shmid指共享内存ID cmd为指令 */ void *shmat( int shmid, const void *shmaddr, int shmflag); /* shmaddr指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置 shmflg SHM_RDONLY:为只读模式,其他为读写模式 */ int shmdt( const void *shmaddr );
例子:

1 #include <stdio.h> 2 #include <sys/ipc.h> 3 #include <sys/shm.h> 4 5 int main() 6 { 7 int shmid; 8 9 shmid = shmget( 0x123, 4096, IPC_CREAT|0666); 10 if(shmid >= 0) 11 printf("Created a shared memory %d\n", shmid); 12 13 return 0; 14 }

1 #include <stdio.h> 2 #include <sys/shm.h> 3 #include <errno.h> 4 #include <sys/ipc.h> 5 #include <sys/types.h> 6 7 int main(int argc, char **argv) 8 { 9 int shmid, ret; 10 struct shmid_ds shmds; 11 12 //获取共享内存 13 shmid = shmget(0x123, 0, 0); 14 15 if(shmid >= 0){ 16 ret = shmctl(shmid, IPC_STAT, &shmds); 17 if(ret == 0){ 18 printf("shared memory size : %d/n", shmds.shm_segsz); 19 printf("attaches number: %d/n", (int)shmds.shm_nattch); 20 }else 21 printf("shmctl error!\n"); 22 }else 23 printf("shared memory not found!\n"); 24 25 return 0; 26 }

1 #include <stdio.h> 2 #include <sys/shm.h> 3 #include <errno.h> 4 #include <sys/ipc.h> 5 #include <sys/types.h> 6 #include <string.h> 7 8 int main(int argc, char **argv) 9 { 10 int shmid, ret; 11 void* mem; 12 13 //获取共享内存 14 shmid = shmget(0x123, 0, 0); 15 16 if(shmid >= 0){ 17 18 mem = shmat( shmid, (const void*)0, 0 ); 19 20 strcpy((char*)mem, "This is a shared memory\n"); 21 22 ret = shmdt(mem); 23 24 }else 25 printf("shared memory not found!\n"); 26 27 return 0; 28 }

1 #include <stdio.h> 2 #include <sys/shm.h> 3 #include <errno.h> 4 #include <sys/ipc.h> 5 #include <sys/types.h> 6 #include <string.h> 7 8 int main(int argc, char **argv) 9 { 10 int shmid, ret; 11 void* mem; 12 13 //获取共享内存 14 shmid = shmget(0x123, 0, 0); 15 16 if(shmid >= 0){ 17 18 mem = shmat( shmid, (const void*)0, 0 ); 19 20 printf("%s", (char*)mem); 21 22 ret = shmdt(mem); 23 24 }else 25 printf("shared memory not found!\n"); 26 27 return 0; 28 }

1 #include <stdio.h> 2 #include <sys/shm.h> 3 #include <errno.h> 4 #include <sys/ipc.h> 5 #include <sys/types.h> 6 7 int main(int argc, char **argv) 8 { 9 int shmid, ret; 10 11 //获取共享内存 12 shmid = shmget(0x123, 0, 0); 13 14 if(shmid >= 0){ 15 ret = shmctl(shmid, IPC_RMID, 0); 16 if(ret == 0){ 17 printf("shared memory removed!"); 18 }else 19 printf("shmctl error!\n"); 20 }else 21 printf("shared memory not found!\n"); 22 23 return 0; 24 }
参考
GNU/Linux环境编程
http://blog.sina.com.cn/s/blog_7f98bac10100s91d.html
http://www.cnblogs.com/joeblackzqq/archive/2011/05/31/2065161.html
Linux 进程间通信 由 cococo点点 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:转载自:cococo点点 http://www.cnblogs.com/coder2012
本文 由 cococo点点 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:
转载自:cococo点点 http://www.cnblogs.com/coder2012
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!