2015.3.4
星期三 阴天

进程间通信:IPC

文件对象:记录文件描述符,文件开关等

IPC标示符:系统全局的流水号
两个进程要通信,打开的是唯一的对象进行通讯,通过key操作

XSI IPC:消息队列,信号量,共享内存。

ipcs 查看ip对象共享内存,信号量,消息队列等信息
ipcrm 删除一个IP对象

Linux为用户提供了完善的,强大的网络功能
完善的内置网络:其他操作系统不包含如此紧密的和内核结合在一起的网络部分

共享内存标示符的获取有两种方法:ftok(pathname,id)另一个是KEY = IPC_CREATE

共享内存的创建,映射,读取状态等操作:(下面这个程序很短,但是基本包含了大部分共享内存函数的应用,程序入门非常好)

消息队列的实例程序;

#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define KEY 1234
#define TEXT_SIZE 48

struct msgbuffer
{
long mtype;
char mtext[TEXT_SIZE];
}msgp;

int mian(int argc, char **argv)
{
int msqid;
msqid = msgget(KEY, IPC_CTEAT | 0600); 建立消息队列

if(fork() == 0)
{
msgp.mtype = 1;
strcpy(msgp.mtext,"hi! I am child process!\n");
msgsnd(msqid,&msgp,TEXT_SIZE,0); 传送消息至队列
return ;
}

else
{
sleep(3); 等子进程执行完毕
msgrcv(msqid,&msgp,TEXT_SIZE,0,0); 接收队列的信息
printf("parent receive mtext : %s",msgp.mtext);
msgctl(msqid,IPC_RMID,NULL): 删除消息队列
}
}

#include <unistd.h>
#include <sys/ipc.h>

#include <sys/shm.h>

#define KEY 1234
#define SIZE 1024

int main(int argc, char **argv)
{
int shmid;
char *shmaddr;
struct shmid_ds buf;

shmid = shmget(KEY,SIZE,IPC_CREAT | 0600); 建立共享内存

if(fork() == 0) 子进程
{
shmaddr = (char *)shmat(shmid,NULL,0); 子进程映射共享内存
strcpy(shmaddr,"hi! I an child process!\n"); 对共享内存写入数据
shmdt(shmaddr); 释放子进程虚拟内存
return;
}

{ 父进程
sleep(3); 等待子进程执行完毕
shmctl(shmid,IPC_STAT,&buf); 取得共享内存的状态
printf("shm_segsz = %d bytes\n",shm_segsz);
printf("shm_cpid = %d bytes\n",shm_cpid);
printf("shm_lpid = %d bytes\n",shm_lpid);

shmaddr = (char *)shmat(shmid,NULL,0); 父进程映射共享内存
printf("%s",shmaddr); 显示共享内存内容
shmdt(shmaddr); 释放父进程虚拟内存
shmctl(shmid,IPC_RMID,NULL); 删除共享内存
}
}

共享内存的另一个程序:

#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#define BUFSZ 2048

int main(int argc, char **argv)
{
int shmid;
char *shmaddr;

if((shmid = shmget(IPC_PRIVATE,BUFSZ,0666)) < 0); IPC_PRIVATE是指定键,保证了能创建一个新的IPC,缺点是获得的标识符写入
{ 了文件中,用户用的时候需要进入文件读取
perror("shmget");
exit(-1);
}

printf("###create shared - memory:%d\n",shmid);

system("ipcs -m | grep 666"); 相当于执行 ipcs -m

if((shmaddr = (char *)shmat(shmid,NULL,0))<(char *)0)
{
perror("shmat");
exit(-1);
}

printf("###create shared - memory\n");

system("ipcs -m | grep 666");

if((shmdt(shmaddr)) < 0)
{
perror("shmdt");
exit(-1);
}

printf("###create shared - memory\n");

system("ipcs -m | grep 666");

shmctl(shmid, IPC_RMID, NULL); 删除共享内存段
printf("###create shared - memory\n");

system("ipcs -m | grep 666");

return 0;

}

创建共享内存和信号灯并初始化,创建子进程,父进程读取标准输入并写入共享内存,子进程打印共享内存中的内容,双方通过信号灯进行同步;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#include <sys/sem.h>

#define READ 0
#define WRITE 1

union semun 这个联合体需要自己定义
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
};

int shmid; 定义的一些全局变量:
int semid;
pid_t pid;

int main()
{
key_t key;
char *shmaddr;
union semun myun;
struct sembuf buf;

if((key = ftok("./",'a')) == -1) 获得键值
{
perror("faile to ftok");
exit(-1);
}

if((shmid = shmget(key,64,IPC_CREAT|0666)) < 0) 建立共享内存,如果存在就取内存ID
{
perror("fail to shmget");
exit(-1);
}

shmaddr = (char*)shmat(shmid,NULL,0); 映射虚拟内存,下面调用fork(),会将映射继承到子进程中,这是创建进程间相同映射的一种方式

if((semid = semget(key,2,IPC_CREAT|0666)) < 0) 创建信号集,信号集中有两个信号
{
perror("fail to semget");
exit(-1);
}

myun.val = 0; 这是一个初始化操作,表示信号量的个数
semctl(semid,READ,SETVAL,myun);
myun.val = 1;
semctl(semid,WRITE,SETVAL,myun);

if((pid = fork()) < 0) 创建子进程
{
perror("fail to fork");
exit(-1);
}
else if(pid == 0)
{
buf.sem_num = READ; 信号个数0
buf.sem_op = -1; p操作,信号量小于等于0则阻塞 (sem_wait()函数) 3.在2之后开始执行
buf.sem_flg = 0;
semop(semid,&buf,1);
printf("read from shm : %s",shmaddr);
buf.sem_num = WRITE; 信号个数1
buf.sem_op = 1; v操作 (sem_post()函数)将信号 4.将信号量个数置0,子进程等待。
buf.sem_flg = 0;
semop(semid,&buf,1);
}
else
{
buf.sem_num = WRITE; 信号个数
buf.sem_op = -1; p操作 (sem_post()函数) 1.执行
buf.sem_flg = 0;
semop(semid,&buf,1);
printf("write to shm : ");
fgets(shmaddr,64,stdin);
buf.sem_num = READ; 信号个数0
buf.sem_op = 1; V操作 (sem_wait()函数) 2.唤醒子进程的等待程序
buf.sem_flg = 0;
semop(semid,&buf,1);
}

return 0;
}

***************************************************************************************************************************************************************
***************************************************************************************************************************************************************
***************************************************************************************************************************************************************
***************************************************************************************************************************************************************

进程间通信IPC:消息队列,信号量,共享内存的更多相关文章

  1. Linux进程间通信(消息队列/信号量+共享内存)

    写在前面 不得不说,Deadline果真是第一生产力.不过做出来的东西真的是不堪入目,于是又花了一早上重写代码. 实验内容 进程通信的邮箱方式由操作系统提供形如 send()和 receive()的系 ...

  2. 进程间通信之信号量、消息队列、共享内存(system v的shm和mmap)+信号signal

    进程间通信方式有:System v unix提供3种进程间通信IPC:信号量.消息队列.共享内存.此外,传统方法:信号.管道.socket套接字. [注意上述6种方式只能用户层进程间通信.内核内部有类 ...

  3. Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字

    Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...

  4. boost进程间通信经常使用开发一篇全(消息队列,共享内存,信号)

    本文概要: 敏捷开发大家想必知道并且评价甚高,缩短开发周期,提高开发质量.将大project独立为不同的小app开发,整个开发过程,程序可用可測,所以提高了总体的质量.基于这样的开发模式和开发理念,进 ...

  5. 8.7 进程间的通讯:管道、消息队列、共享内存、信号量、信号、Socket

    进程间的通讯 进程间为什么需要通讯? 共享数据.数据传输.消息通知.进程控制 进程间的通讯有哪些类型? 首先,联系前面讲过的知识,进程之间的用户地址空间是相互独立的,不能进行互相访问,但是,内核空间却 ...

  6. linux IPC 消息队列

    消息队列函数原型 在建立IPC通讯时(如消息队列,共享内存)必须建立一个ID值.通常情况下,这个ID值由ftok函数得到 #inlcude <sys/types.h> #include & ...

  7. IPC——消息队列

    Linux进程间通信——使用消息队列 下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管 ...

  8. c/c++ linux 进程间通信系列4,使用共享内存

    linux 进程间通信系列4,使用共享内存 1,创建共享内存,用到的函数shmget, shmat, shmdt 函数名 功能描述 shmget 创建共享内存,返回pic key shmat 第一次创 ...

  9. [原创]chromium源码阅读-进程间通信IPC.消息的接收与应答

    chromium源码阅读-进程间通信IPC.消息的接收与应答   chromium源码阅读-进程间通信IPC.消息的接收与应答 介绍 chromium进程间通信在win32下是通过命名管道的方式实现的 ...

  10. PHP进程通信基础——信号量+共享内存通信

    PHP进程通信基础--信号量+共享内存通信 由于进程之间谁先执行并不确定,这取决于内核的进程调度算法,其中比较复杂.由此有可能多进程在相同的时间内同时访问共享内存,从而造成不可预料的错误.信号量这个名 ...

随机推荐

  1. 有向图的强连通图——Kosaraju

    有向图的强连通分量: 相互可达关系,每一个集合都是有向图的一个强连通分量SCC. 把一个集合看成一个点,SCC就形成了一个有向无环图——DAG;       如果DFS选择不好,从A点开始DFS,就会 ...

  2. 【前端】Web前端学习笔记【1】

    ... [2015.12.02-2016.02.22]期间的学习笔记. 相关博客: Web前端学习笔记[2] 1. JS中的: (1)continue 语句 (带有或不带标签引用)只能用在循环中. ( ...

  3. [问题2014S15] 复旦高等代数II(13级)每周一题(第十五教学周)

    [问题2014S15]  设 \(O\) 为 \(n\) 阶正交阵,\(A=\mathrm{diag}\{a_1,a_2,\cdots,a_n\}\) 为实对角阵, 证明: 方阵 \(OA\) 的特征 ...

  4. PHP : Reflection API

    PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类.方法.属性.参数等的详细信息,包括注释. PHP Reflection API有: class Reflecti ...

  5. Await Async Task

    class Program { static void Main(string[] args) { Console.WriteLine("=======Start Main!======== ...

  6. RMAN的入门篇

    一.RMAN连接数据库 1.  连接本地数据库 [oracle@oracle hotbak]$ export oracle_sid=orcl [oracle@oracle hotbak]$ rman ...

  7. 当 IDENTITY_INSERT 设置为 OFF 时,不能为表‘XXX’中的标识列插入显式值。

    在创建事务复制时,很多时候不一定使用快照进行初始化,而是使用备份还原初始化.当对有标识列(即identity的自增列)的表进行复制的时候,使用备份还原初始化搭建起来的复制常常就会报错,即:当 IDEN ...

  8. WIN7 java7 环境变量配置

    1 首先要搞清楚,java可能安装了两个部分,一个叫JDK,一个叫jre.其中jre若已经安装了,那么在安装JDK的时候,就不要放在默认的C:\Program File\java\XXX目录.最好另起 ...

  9. Octopus系列之价格计算公式

    百分比:在原价的基础上优惠5%,相当于95%折销售实际价格:最后实际销售的价格[基准价格:如果有特价就基于特价,没有特价基于原价]优惠金额:减少的金额 批量优惠 百分比: 原价*(1-5%)的算法实际 ...

  10. input框限制只能输入正整数,逻辑与和或运算

    推荐下自己刚写的项目,请大家指正:童话之翼 有时需要限制文本框输入内容的类型,本节分享下正则表达式限制文本框只能输入数字.小数点.英文字母.汉字等代码. 例如,输入大于0的正整数 代码如下: < ...