【Linux编程】XSI IPC
来源:互联网 发布:visio 软件开发流程图 编辑:程序博客网 时间:2024/06/01 13:13
三种IPC被称作XSI IPC,分别是:
- 消息队列
- 信号量
- 共享存储器
下面分别介绍三种IPC的用法。
1、消息队列
消息队列是消息的链接表,具有如下函数接口:
- msgget:创建一个新队列或打开一个现存的队列。
- msgsnd:将消息添加到队列尾端。
- msgrcv:从队列中取消息。
我们可以自行定义一个表示消息的结构体,它由类型字段和实际数据组成:
struct mest_t { long type; // 消息类型 char text[512]; // 消息内容};
有了消息类型,当我们用msgrcv函数取消息时,就不一定要以先进先出的顺序,而是可以根据消息类型取消息了。下面是一段简单的测试代码:
#include <stdio.h>#include <sys/msg.h>#include <sys/types.h>#include <string.h>#include <errno.h> struct mest_t { long type; char text[512];}; int main(void){ pid_t pid; int mq_id; struct mest_t msg; /* IPC_PRIVATE用于创建一个新队列 * 设置了IPC_EXCL并且设置了IPC_CREAT,当文件存在时返回错误 */ mq_id = msgget(IPC_PRIVATE, IPC_CREAT | IPC_EXCL); if (mq_id == EEXIST) return -1; /* 返回EEXIST表示IPC已存在 */ if ((pid = fork()) < 0) return -1; else if (pid == 0) { /* 子进程 */ msg.type = 123; /* 消息类型 */ strcpy(msg.text, "Hello world!"); /* 消息内容 */ /* 非阻塞方式将消息放入消息队列 * 队列已满则返回EAGAIN */ while (msgsnd(mq_id, (long *)&msg, 512, IPC_NOWAIT) == EAGAIN) sleep(1); } else { /* 非阻塞方式从队列中取消息 * 如果没有指定类型的消息,函数返回-1,errno设置为ENOMSG */ while (msgrcv(mq_id, (long *)&msg, 512, 123, IPC_NOWAIT) == -1) { if (errno == ENOMSG) { printf("There is no this type message!\n"); sleep(1); } } printf("%s\n", msg.text); } return 0;}
当父进程需要取的消息类型和子进程发送的消息类型相同时,运行结果如下:
父进程能够很快接收到子进程发送到消息队列中的消息。但是修改msgrcv的消息类型参数后,运行结果如下:
父进程得不到想要的消息,一直打印错误信息。
2、信号量
信号量是一个计数器,用于多进程对共享数据对象的访问。过程如下:
- 测试控制该资源的信号量。
- 若此信号量的值为正,则进程可以使用该资源。进程将信号量值减1,表示它使用了一个资源单位。
- 若此信号量的值为0,则进程进入休眠状态,直至信号量大于0。进程被唤醒后,它返回至第一步。
当进程不再使用由一个信号量控制的共享资源时,该信号量值增1。如果有进程正在休眠等待此信号量,则唤醒它们。
3、共享存储
共享存储允许多个进程共享一块给定的存储区,是最快的一种IPC。测试代码如下:
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/shm.h> #define SHM_SIZE 100#define SHM_MODE (SHM_W | SHM_R | IPC_CREAT) int main(){ int shmid; char *shmptr; pid_t pid; /* 获得共享存储标识符 */ if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0) return -1; if ((pid = fork()) < 0) return -1; else if (pid == 0) { shmptr = shmat(shmid, 0, 0); /* 参数2为0表示由内核分配共享空间 */ printf("Child attached shared memory is : %lx\n", (unsigned long)shmptr); shmdt(shmptr); /* 使进程脱离该共享空间 */ } else { waitpid(pid, NULL, 0); shmptr = shmat(shmid, 0, 0); printf("Parent attached shared memory is : %lx\n", (unsigned long)shmptr); shmdt(shmptr); shmctl(shmid, IPC_RMID, 0); /* 删除该共享存储段 */ } return 0;}
运行结果:
从上面的实验结果可以看出,父、子进程共享了同一个存储段。有一点需要注意,shmdt函数只是让进程脱离该共享存储段,但该存储段依然存在并且shmid依然有效,它是与shmat相对应的。而另一个函数shmctl使用IPC_RMID参数时才是真正删除该共享段。
共享存储段和存储映射I/O中的mmap函数非常相似,它们之间的区别是:mmap映射的存储段是与文件相关联的,XSI共享存储段则并无这种关联。
参考:
《unix环境高级编程》 P415-P432.
0 0
- 【Linux编程】XSI IPC
- Linux XSI IPC 之信号量
- 《UNIX环境高级编程》笔记--XSI IPC
- 《UNIX环境高级编程》笔记--XSI IPC
- Linux XSI IPC 之消息队列
- Linux XSI IPC 之共享内存
- 【Linux/OS/Network】XSI IPC(消息队列,信号量,共享内存)
- XSI IPC机制
- 进程通信之XSI IPC
- UNIX网络编程卷2进程间通信读书笔记(四)—XSI IPC
- linux编程之ipc
- 进程间通信之XSI IPC
- XSI IPC之消息队列实例
- XSI IPC 进程间通讯方式
- 【转载】XSI IPC机制的优缺点
- UNIX再学习 -- XSI IPC通信方式
- XSI IPC(消息队列、信号量、共享内存)
- 【Linux编程】IPC之管道
- 那位帮忙提供一个java mongodb多个collection进行mapreduce的操作。
- Swift学习 enum的遍历
- DB2的目录结构(Windows下)
- JVM学习-ClassLoader的父类委托机制
- UVA 10622 - Perfect P-th Powers(数论)
- 【Linux编程】XSI IPC
- web编程之注册以及登录验证模块(PHP+mysql)
- android sdk documentation download
- Introduction to 555 timer 【数字电路】
- SqlHelper类
- nginx源码分析--从源码看nginx框架总结
- java web学习基础(三)4中属性范围 request对象 response对象
- 乘蒙又百彻磐谓曰弥炭松比
- 编译64位 hadoop 2.4 源码