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绝对值的消息中类型值最小的第一条消息
*/
例子:
#include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h> int main()
{
int msgid; //通过这样可以避免标识符的重复
//key_t myKey;
//myKey = ftok("/home/queues/myqueue", 0); msgid = msgget( 0x111, IPC_CREAT|);
if(msgid >= )
printf("Created a Msg Queue %d\n", msgid); return ;
} 创建消息队列
创建消息队列
#include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h> int main(int argc, char **argv)
{
int msgid, ret;
struct msqid_ds buf; //获取消息队列
msgid = msgget(0x111, ); if(msgid >= ){
ret = msgctl(msgid, IPC_STAT, &buf);
buf.msg_qbytes = ; ret = msgctl(msgid, IPC_SET, &buf); if(ret == ){
printf("change queue size success");
}
} return ;
}
配置消息队列
#include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h> typedef struct{
long type;
float fval;
unsigned int unival;
char message[];
}myType; int main()
{
myType msg;
int qid,ret; qid = msgget(0x111, );
if(qid > ){
msg.type = 1L;
msg.fval = 123.456;
msg.unival = ;
strcpy( msg.message, "this is a msg in queue\n"); ret = msgsnd(qid, (struct msgbuf*)&msg, sizeof(myType), );
if(ret != -)
printf("sent success!\n");
} return ;
}
向消息队列发送消息
#include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h> typedef struct{
long type;
float fval;
unsigned int unival;
char message[];
}myType; int main()
{
myType msg;
int qid,ret; qid = msgget(0x111, );
if(qid >= ){ ret = msgsnd(qid, (struct msgbuf*)&msg, sizeof(myType), );
if(ret != -)
printf("recv success!\n");
printf("type : %ld\n", msg.type);
printf("float value: %f\n", msg.fval);
printf("Unit value: %d\n", msg.unival);
printf("String value: %s\n", msg.message);
} return ;
}
从消息队列读取消息
共享内存
使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间的一次复制,当另外一个进程要从消息队列中读取消息时,又要进行一次从内核空间向用户空间的一次复制。而共享内存的优点就是完全省去了这些复制操作。
简单介绍下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 );
例子:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h> int main()
{
int shmid; shmid = shmget( 0x123, , IPC_CREAT|);
if(shmid >= )
printf("Created a shared memory %d\n", shmid); return ;
}
创建共享内存
#include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h> int main(int argc, char **argv)
{
int shmid, ret;
struct shmid_ds shmds; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){
ret = shmctl(shmid, IPC_STAT, &shmds);
if(ret == ){
printf("shared memory size : %d/n", shmds.shm_segsz);
printf("attaches number: %d/n", (int)shmds.shm_nattch);
}else
printf("shmctl error!\n");
}else
printf("shared memory not found!\n"); return ;
}
取得共享内存
#include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <string.h> int main(int argc, char **argv)
{
int shmid, ret;
void* mem; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){ mem = shmat( shmid, (const void*), ); strcpy((char*)mem, "This is a shared memory\n"); ret = shmdt(mem); }else
printf("shared memory not found!\n"); return ;
}
写入共享内存
#include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <string.h> int main(int argc, char **argv)
{
int shmid, ret;
void* mem; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){ mem = shmat( shmid, (const void*), ); printf("%s", (char*)mem); ret = shmdt(mem); }else
printf("shared memory not found!\n"); return ;
}
读取共享内存
#include <stdio.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h> int main(int argc, char **argv)
{
int shmid, ret; //获取共享内存
shmid = shmget(0x123, , ); if(shmid >= ){
ret = shmctl(shmid, IPC_RMID, );
if(ret == ){
printf("shared memory removed!");
}else
printf("shmctl error!\n");
}else
printf("shared memory not found!\n"); return ;
}
删除共享内存
参考
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
Linux 进程间通信(一)的更多相关文章
- Linux进程间通信(一): 信号 signal()、sigaction()
一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...
- Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()
我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...
- Linux进程间通信(三):匿名管道 popen()、pclose()、pipe()、close()、dup()、dup2()
在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据. 一.什 ...
- Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close()
在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关 ...
- Linux进程间通信(五):信号量 semget()、semop()、semctl()
这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信 -- 信号.下面 ...
- Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()
下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...
- Linux进程间通信(七):消息队列 msgget()、msgsend()、msgrcv()、msgctl()
下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信 -- 使用命名管道 一.什么是消息队列 消息队列提 ...
- Linux进程间通信(九):数据报套接字 socket()、bind()、sendto()、recvfrom()、close()
前一篇文章,Linux进程间通信——使用流套接字介绍了一些有关socket(套接字)的一些基本内容,并讲解了流套接字的使用,这篇文章将会给大家讲讲,数据报套接字的使用. 一.简单回顾——什么是数据报套 ...
- [转]Linux进程间通信——使用消息队列
点击此处阅读原文 另收藏作者ljianhui的专栏初学Linux 下面来说说如何使用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linu ...
- Linux 进程间通信(二) 管道
Linux 进程间通信-管道 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及 ...
随机推荐
- CSS BOX模型
对于box模型概念的理解以及它与决定元素最终尺寸的方式有何关系,是理解如何设定网 页上的元素位置的基础.box模型应用到块级元素.一个随之而来的概念,内联布局模型 定义了如何设定内联元素的位置. 对于 ...
- 循序渐进Python3(二) -- 数据类型
数据类型 一.数字(int) Python可以处理任意大小的正负整数,但是实际中跟我们计算机的内存有关,在32位机器上,整数的位数为32位,取值范围为 -2**31-2**31-1,在64位系统上,整 ...
- 构建ASP.NET网站十大必备工具(2)
正常运行时间 当一个网站发布以后,你肯定希望你的网站不会遇到任何问题,一直处在正常运行状态之中.现在,我使用下面这些工具来监控“Superexpert.com”网站,确保它一直处在正常运行状态之中. ...
- CoreData创建
云盘-->CoreData文件 一 创建表打开点击增加的Entity名字应该与 EntityForName一致 二 创建NSManageObject SubClass 三 拖进CoreD ...
- 项目Windows服务安装命令:
sc create YY.SmsPlatform.RemoteDataCenter binPath= "E:\YY.SmsPlatform\YY.SmsPlatform.RemoteData ...
- Android 环境通过国内映像快速搭建
Android 环境通过国内映像快速搭建 转眼大半年没有写android程序了,回顾从环境搭建开始. 因为google受国内限制,因此下载android的SDK相当慢,因此寻找国内的镜像进行搭建. 首 ...
- java基础之:堆排序
最近做题目饱受打击,愈发觉得打好基础的重要性,于是乎,决心把基本的排序算法还有数组操作一一实现,目的在于一方面能够得到对JAVA基础的巩固,另一面在实现的过程中发现不足. 今天所实现的堆排序(最大堆) ...
- IT公司笔试题(一)
1. 已知一个递归算法的算法复杂度计算公式为T(n) = T(n/2) + n,则T(n)的算法复杂度为多少? 解:O(n) T(n) = T(n/2) + n = T(n/4) + n/2 + n ...
- 2015年九月八日---js学习总结
参考书:javaScript Dom 编程的艺术 知识小结:一:js简史:前称ECMAScript 是一种脚本语言通常只能通过浏览器进行解释和执行. Dom(文档对象模型):是一套对文档的内容进行抽象 ...
- MySQL报错“1366 - Incorrect integer value: '' XXXXXXX' at row 1 ”
出现这个错误是因为我在表中插入了一条含有中文字符的语句: 修改方法:(两种) 1:命令行 set names gbk:(此为设置通信编码) 2:my.ini中查找sql-mode 将 sql-mod ...
