linux进程通信全面解析
进程IPC 的 7种方式
1.文件 ,记得 加文件锁 lockf.使用少,略去
2.共享内存
POSIX 共享内存的api:
| 函数 | 作用 |
| shm_open | 创建一个新的共享区域或者附加在已有的共享区域上,区域被其名字标识,函数返回各文件的描述符,类似于open系统调用 |
| shm_unlink | 对 shm_open 返回的文件描述符 共享区域进行释放,类似于使用 unlink系统调用 对文件进行操作,知道所有的进程都不再饮用该内存后才对其进行释放。 |
| mmap | 用于将一个文件 映射到 某一个内存区中,其中 也使用来shm_open返回的文件描述符,函数的返回值 是指向文件映射到内存地址的指针。mmap同样可以 使用纯文本文件 和一些 驱动程序的文件描述符 |
| munmap | 用于释放mmap所映射的内存区域 |
| msync | 同步存取一个映射区域 并将高速缓存的数据 回写到物理内存中,以便其他进程可以舰艇这些改变 |
例子 程序:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/file.h>
#include<sys/mman.h>
#include<sys/wait.h>
void error_out(constchar* msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc,char*argv[])
{
int r;
constchar*memname ="/mymen";
constsize_t region_size = sysconf(_SC_PAGE_SIZE);
//create the share memory region
int fd = shm_open(memname,O_CREAT | O_TRUNC | O_RDWR,);
if(fd ==-)
error_out("shm_open");
//allocate some memory in the region ,
r = ftruncate(fd,region_size);
if(r !=)
error_out("ftruncate");
//map the region into the memory
void*ptr = mmap(,region_size,PROT_READ | PROT_WRITE ,MAP_SHARED,fd,);
if(ptr == MAP_FAILED)
error_out("mmap");
//useness after mmap called
close(fd);
pid_t pid = fork();
//child
if(pid ==)
{
u_long *d =(u_long*)ptr;
*d =0xfdefdddd;
exit();
}
//parent
else{
int status;
waitpid(pid,&status,);
printf("child wrote %#1x\n",*(u_long*)ptr);
}
//release memory
//umap
r = munmap(ptr,region_size);
if(r !=)
error_out("munmap");
r = shm_unlink(memname);
if(r !=)
error_out("shm_ulink");
return0;
}
System V 共享内存的api
| 函数 | 作用 |
| shmget | 创建一个新的共享区域或者已有的共享区域上(同shm_open +一个内存申请函数) |
| shmat | 用于将一个文件 映射到内存区域中(同mmap) |
| shmdt | 用于释放所映射的内存区域(同munmap ) |
| shmct | 对用多个用户,断开其对共享区域的连接(同shm_unlink) |
例子 ,同上 ,功能完全一样:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/ipc.h>
#include<sys/shm.h>
#include<sys/wait.h>
void error_out(constchar* msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc,char*argv[])
{
int r;
key_t mykey =;
constsize_t region_size = sysconf(_SC_PAGE_SIZE);
//create the shared memory region
int shmid = shmget(mykey,region_size,IPC_CREAT |);
if(shmid ==-)
error_out("shmget");
//map the region into memory
void*ptr = shmat(shmid,NULL,);
if(ptr ==(void*)-)
error_out("shmat");
//useness after mmap called
pid_t pid = fork();
//child
if(pid ==)
{
u_long *d =(u_long*)ptr;
*d =0xfdefdddd;
exit();
}
//parent
else{
int status;
waitpid(pid,&status,);
printf("child wrote %#1x\n",*(u_long*)ptr);
}
//release memory
//umap
r = shmdt(ptr);
if(r ==-)
error_out("shmdt");
//remove the shared memory region
r = shmctl(shmid,IPC_RMID,NULL);
if(r ==-)
error_out("shmctl");
return0;
}
3.信号
4.管道
5.套接字
6.消息列队
system V api:
| 函数 | 作用 |
| int msgget(key_t key,int msgflg); | 创建或者附加一个消息列队,返回一个msgID |
| int msgctl(int msgid,int cmd,struct msgid_ds *buf) | 可以用于删除一个msgID,当buf参数为空的情况下,删除消息列队的cmd为ipc_rmid |
| int msgsnd(int qid,void* msg,size_t msgsz,int msgflg) | 发送() |
| ssize_t msgrcv(int qid,void* msg,size_t msgsz,int msgflg) | 接收() |
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<sys/file.h>
#include<sys/msg.h>
#include<sys/ipc.h>
struct message
{
longint mtype;
char mtext[];
};
void error_out(constchar* msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
//send msg
int send_msg(int qid,int mtype,constchar text[])
{
struct message msg ={
.mtype = mtype
};
strncpy(msg.mtext,text,sizeof(msg.mtext));
int r = msgsnd(qid,&msg,sizeof(msg),);
if(r ==-)
error_out("msgsnd");
return r;
}
//recv msg
int recv_msg(int qid,int mtype,struct message* msg)
{
int r = msgrcv(qid,msg,sizeof(struct message),mtype,);
switch(r)
{
casesizeof(struct message):
break;
case-:
perror("msgrcv");
break;
default:
printf("only recv %d bytes data\n",r);
break;
}
return r;
}
void producer(int mqid)
{
send_msg(mqid,,"type 1 - first");
send_msg(mqid,,"type 2 - second");
send_msg(mqid,,"type 1 - thrid");
}
void consumer(int qid)
{
struct message msg;
int r ;
int i ;
for(i =;i <;++i)
{
r = msgrcv(qid,&msg,sizeof(struct message),-,);
printf("[%s]\n",msg.mtext);
}
}
int main(int argc ,char*argv[])
{
//create a private (unname) message queue
int mqid;
mqid = msgget(IPC_PRIVATE,S_IREAD | S_IWRITE);
if(mqid ==-)
error_out("msgget");
pid_t pid = fork();
if(pid ==)
{
consumer(mqid);
exit();
}
else
{
int status;
producer(mqid);
wait(&status);
}
//remove the message queue
int r = msgctl(mqid,IPC_RMID,);
if(r)
perror("msgctl");
return0;
}
- 正数,只接受 该类型的消息
- 负数,只接受 小于或者等于 指定类型绝对值 的消息
posix api : 略去
7.信号量 semaphore
posix api:
| 函数 | 作用 |
| sem_t *sem = sem_open() | 创建信号量 并初始化为0 |
| sem_post(sem ) | 信号量 +1 |
| sem_wait(sem ) | 信号量 -1 |
system V API
| 函数 | 作用 |
| semget | 生成 信号量ID, |
| semop | 通过不同的op,增或者 减 信号量 |
具体例子 可以百度下。
linux进程通信全面解析的更多相关文章
- Linux进程通信----匿名管道
Linux进程通信中最为简单的方式是匿名管道 匿名管道的创建需要用到pipe函数,pipe函数参数为一个数组表示的文件描述字.这个数组有两个文件描 述字,第一个是用于读数据的文件描述符第二个是用于写数 ...
- Linux 进程通信之 ——信号和信号量总结
如今最经常使用的进程间通信的方式有:信号,信号量,消息队列,共享内存. 所谓进程通信,就是不同进程之间进行一些"接触",这种接触有简单,也有复杂.机制不同,复杂度也不一 ...
- Linux进程通信学习总结
http://blog.csdn.net/xiaoweibeibei/article/details/6552498 SYSV子系统的相关概念 引用标识符:引用标识符是一个整数,表示每一个SYSV ...
- Linux进程通信的几种方式总结
进程通信的目的 数据传输 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程需要向另一个或一组进程发 ...
- linux进程通信之管道
1.介绍: 1)同一主机: unix进程通信方式:无名管道,有名管道,信号 system v方式:信号量,消息队列,共享内存 2)网络通信:Socket,RPC 2.管道: 无名管道(PIPE):使用 ...
- linux 进程通信之 共享内存
共享内存是被多个进程共享的一部分物理内存.共享内存是进程间共享数据的一种最快的方法.一个进程向共享内存区域写入了数据,共享这个内存区域的全部进程就能够立马看到当中的内容. 关于共享内存使用的API k ...
- linux进程通信
e14: 进程间通信(进程之间发送/接收字符串/结构体): 传统的通信方式: 管道(有名管道 fifo,无名管道 pipe) 信号 signal System V(基于IPC的对象): ...
- linux 进程通信 管道
1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...
- Linux进程通信——管道
管道(pipe)本质上是一种文件,管道通信本质上是通过读写文件通信,但是管道解决了文件的两个问题:限制管道大小,解决read()调用文件结束问题. 管道一个环形的缓冲区,通过两个进程以生产者/消费者的 ...
随机推荐
- xx-net***简明使用教程
简介 继psiphon3.lantern.shadowsocks后,翻 土啬 界就来个新角色:xx-net 这张图是.2016.8.30日Google最新的搜索结果,还是可以看出这款工具的火爆程度的, ...
- HDU4639
/*计算里面有多少个相邻的he,1个he就是1种意思,两个就是,两种,所以这是 一个斐波拉期数列,间隔的hehe互不影响所以是互斥事件,直接相乘就可以*/ #include<stdio.h> ...
- linux 查看内存信息,及其他硬件信息 dmidecode命令
由于想换内存,想看看内存型号.频率,简单搜了下命令 可以用dmidecode 命令查看. dmidecode -t memory 这个命令可以查看内存的几乎所有信息,包括频率 大小等等 另外这个命令强 ...
- 20145120黄玄曦《网络对抗》MSF基础应用
20145120黄玄曦<网络对抗>MSF基础应用 准备工作 本来决定就是老师提供的XP虚拟机了,做着做着发现因为打补丁以及语言的问题,需要另外的虚拟机. 求来了不那么健壮的虚拟机,环境如下 ...
- 20145240 GDB调试汇编堆栈过程分析
20145240 GDB调试汇编堆栈过程分析 测试代码 #include<stdio.h> short addend1 = 1; static int addend2 = 2; const ...
- 20145201 《Java程序设计》第五周学习总结
20145201 <Java程序设计>第五周学习总结 教材学习内容总结 本周学习了课本第八.九章内容,即异常处理.Collection与Map. 第八章 异常处理 8.1 语法与集成架构 ...
- Eclipse调试C++(Cocos2dx Android )
原文链接: http://www.cnblogs.com/zouzf/p/4202537.html 先说windows下的,mac下的在最后 环境:win8.1.java 1.5.Eclipse 4. ...
- 关于div可编辑的复制粘贴问题
todoFilter(e) { e.preventDefault(); if (!e.target.getAttribute('contenteditable')) { return; } const ...
- 关于PropertyGrid控件的排序问题
前些天,由于在项目中需要用到PropertyGrid这个控件,展现其所在控件的某些属性,由于有些控件的属性较多,不易浏览,而且PropertyGrid的排序默认的按照字母的顺序排列的,这样导致在在某些 ...
- 使用shiro缓存用户身份信息的时候报:java.io.NotSerializableException: org.apache.shiro.util.SimpleByteSource
最近在使用shiro缓存用户的身份信息的时候,报了simpleByteSource不能序列化,跟进源码一看,原来这个类没有实现序列化的接口,但是我在缓存身份信息的实现又要用到这个类,解决方法:重写一个 ...