进程间通讯与同步的实现
来源:互联网 发布:软件商务网 编辑:程序博客网 时间:2024/05/22 11:30
进程通讯
内存共享
A进程创建共享区 shmget(…)
映射内存共享区 shmat(…)
B进程通过key找到共享区 映射内存共享区
进程间通讯
撤销各自的内存映射 shmdt()
删除共享区 shctl()管道Pipe
A进程与B进程进行相互通讯 需要建立两个管道
当A->B时,需要在A中write end 在B中read end;当写入满时,管道阻塞;当管道无东西看读时 同样阻塞;
***以下代码为Xcode上的实现 因为VS下不支持某些类库 ***//// main.c// PipeSample//// Created by Lean on 15/8/2.// Copyright (c) 2015年 WB. All rights reserved.//#include <stdio.h>#include <stdlib.h>#include <sys/wait.h>//提供 wait函数#include <unistd.h>//提供进程#include <string.h>int main(int argc, const char * argv[]) { int pipe_fd[2];//管道的read end和write end pid_t child_pid; char pipe_buf; //初始化 memset(pipe_fd, 0, sizeof(int)*2); //通过pipe打开读写端口,因为管道是单向性的 所以需要两条管道 if (pipe(pipe_fd)==-1) return -1; //fork一个子进程 child_pid=fork(); if (child_pid==-1) return -1; if (child_pid==0) { //关闭写端 close(pipe_fd[1]); while (read(pipe_fd[0], &pipe_buf,1)>0) { write(STDOUT_FILENO, &pipe_buf, 1); } close(pipe_fd[0]); }else{ close(pipe_fd[0]); write(pipe_fd[1], "H", 1); write(pipe_fd[1], "k", 1); close(pipe_fd[1]); wait(NULL); } return 0;}
- Unix Domain Socket(UDS)
服务端监听IPC请求
客户端发起IPC请求
建立IPC连接
客户端向服务端发送数据
***以下代码为示例代码 非运行代码***//// svr_for_uds.c// PipeSample//// Created by Lean on 15/8/2.// Copyright (c) 2015年 WB. All rights reserved.//#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/types.h>#define UDS_PATH "uds_test"#define BUFF_SIZE 100int uds_client(){ int socket_client=-1; int data_len=0; size_t addr_size=0; struct sockaddr_un addr_srv; char str[100]; memset(str, 0, sizeof(char)*100); strcpy(str, "This is the test for UDS"); if ((socket_client=socket(AF_UNIX, SOCK_STREAM, 0))<0) { return -1; } addr_srv.sun_family=AF_UNIX; strcpy(addr_srv.sun_path,UDS_PATH); addr_size=offsetof(struct sockaddr_un, sun_path)+strlen(addr_srv.sun_path); if (connect(socket_client, (const struct sockaddr *)&addr_srv, addr_size)<0) { return -1; } if (send(socket_client, str, strlen(str), 0)<0) { close(socket_client); return -1; } if ((data_len=recv(socket_client, str, 100, 0))>0) { str[data_len]='\0'; printf("echo from server :%s",str); return 0; }else{ close(socket_client); return -1; }}int uds_server(){ int socket_srv=-1; int socket_client=-1; struct sockaddr_un addr_srv,addr_client; char str[BUFF_SIZE]; memset(str,0, sizeof(char)*BUFF_SIZE); if ((socket_srv=socket(AF_UNIX,SOCK_STREAM, 0))<0) { return -1; } addr_srv.sun_family=AF_UNIX; strcpy(addr_srv.sun_path, UDS_PATH); if (bind(socket_srv, (struct sockaddr *)&addr_srv, offsetof(struct sockaddr_un,sun_path)+strlen(addr_srv.sun_path))<0) { return -1; } if (listen(socket_srv, 5)<0) { return -1; } while (1) { size_t nRecv; size_t sz=sizeof(addr_client); if ((socket_client=accept(socket_srv, (struct sockaddr *)&socket_client, &sz))==-1) { return -1; } if ((nRecv=recv(socket_client, str, 100, 0))<0) { close(socket_client); break; } if (send(socket_client, str, nRecv, 0)<0) { close(socket_client); break; } close(socket_client); } return 0;}
- Rremote Procedure Calls(RPC)
客户端进程调用Stub接口
Stub根据操作系统要求进行打包 并由内核来负责传输给服务器内核
服务器端Stub进行解压并调用程序包匹配的进程
服务端进程执行操作。
服务器以以上的过程将结果传递给客户端。
同步机制
- 信号量Semaphore
Semaphore S(信号量)指示共享资源的可用数量,初始化为1
Operation P 也表达为wait()
当进程想进入共享区执行P操作,减少S计数,如果计数>=0,则可以操作共享资源,
否则则加入等待队列,直到某进程释放共享资源后,再从等待队列中取出某个资源。
Operation V 也表达为signal()
当进程想退出共享区执行V操作增加S计数,信号量加一,如果此时信号量>0,
则说明没访问资源的等待者,直接返回。否则V操作要唤醒等待队列中的相关对象。
例子:
假设你有很多相互协作的进程,它们正在读或写一个数据文件中的记录。你可能希望严格协调对这个文件的存取,于是你使用初始值为1的信号量,
在这个信号量上实施两个操作,首先测试并且给信号量的值减1,然后测试并给信号量的值加1。当第一个进程存取文件时,它把信号量的值减1,
并获得成功,信号量的值现在变为0,这个进程可以继续执行并存取数据文件。但是,如果另外一个进程也希望存取这个文件,
那么它也把信号量的值减1,结果是不能存取这个文件,因为信号量的值变为-1。这个进程将被挂起,直到第一个进程完成对数据文件的存取。
当第一个进程完成对数据文件的存取,它将增加信号量的值,使它重新变为1,现在,等待的进程被唤醒,它对信号量的减1操作将获得成功。 - 互斥体Mutex
默认对信号量的操作为Counting Semaphore,而对于存取值为0/1的信号量成为Binary Semaphore,
其表示一个资源是否被占用的两种状态 - 管程Monitor
管程是对信号量机制的延伸和改善,是一种更为轻便的同步手段。
管程是可以被多个进程、线程安全访问的对象和模块,同时受Mutex保护,意味着同一时刻只能有一个访问者访问他们。
实现管程机制的语言有Delphi,Java,Python,Ruby,C#等。
特性:安全性 互斥性 共享性。
Android同步机制具体实现
- Mutext 基于pthread接口的再封装。
Android4.4.2源码/system/core/include/utils/Mutex.h
lock() 获取资源锁 如果资源可用 函数马上返回 如果资源不可用 则形成阻塞
unlock() 释放资源锁 如果有等待的进程 则唤醒等待的进程
trylock() 获取资源锁 如果资源可用 则获取并返回0,如果资源不可用则返回并返回不为0.
inline Mutex::~Mutex() { pthread_mutex_destroy(&mMutex);}inline status_t Mutex::lock() { return -pthread_mutex_lock(&mMutex);}inline void Mutex::unlock() { pthread_mutex_unlock(&mMutex);}inline status_t Mutex::tryLock() { return -pthread_mutex_trylock(&mMutex);}
AutoLock构造函数获取一个Binary Semaphore并对其加锁,析构函数对其Mutex解锁
class Autolock { public: inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } inline ~Autolock() { mLock.unlock(); } private: Mutex& mLock; };
- Condition
Android4.4.2源码/system/core/include/utils/Condition.h 依赖Mutex完成
由于某个进程需要达到一定的条件才会执行某行代码,如果采用轮询的方法效率底下。Condition就是被设计为解决此类特殊的需求问题。
wait() 等待某个条件满足,至于条件是什么,系统并不理会,相当于“黑盒”设计。
enum WakeUpType { WAKE_UP_ONE = 0, WAKE_UP_ALL = 1 }; // Wait on the condition variable. Lock the mutex before calling. //释放锁 睡眠 添加锁 inline status_t Condition::wait(Mutex& mutex) { return -pthread_cond_wait(&mCond, &mutex.mMutex); } // same with relative timeout status_t waitRelative(Mutex& mutex, nsecs_t reltime); // Signal the condition variable, allowing one thread to continue. void signal(); // Signal the condition variable, allowing all threads to continue. void broadcast(); enum { PRIVATE = 0, SHARED = 1 };
- Barrier E:/Android4.4.2源码/frameworks/native/services/surfaceflinger/Barrier.h
基于Mutext与Condition完成的一个模型。即“Barrier”是填充了条件的Condition。
Barrier是专门为SurfaceFlinger而设计的。
Mutex::Autolock _l(lock);保持操作原子性。
public: inline Barrier() : state(CLOSED) { } inline ~Barrier() { } void open() { Mutex::Autolock _l(lock); state = OPENED; cv.broadcast(); } void close() { Mutex::Autolock _l(lock); state = CLOSED; } void wait() const { Mutex::Autolock _l(lock); while (state == CLOSED) { //释放锁 进入休眠 完了再获取锁 cv.wait(lock); } }private: enum { OPENED, CLOSED }; mutable Mutex lock; mutable Condition cv; volatile int state;};
参考文献:
Linux进程间通信之信号量(semaphore)、消息队列(Message Queue)和共享内存(Share Memory)
http://www.cnblogs.com/biyeymyhjob/archive/2012/11/04/2753535.html
1 0
- 进程间通讯与同步的实现
- c# 进程间同步实现 进程之间通讯的几种方法
- c# 进程间同步实现 进程之间通讯的几种方法
- c# 进程间同步实现 进程之间通讯的几种方法
- PHP进程与进程间的通讯
- VB 进程间同步通讯
- 线程,进程间的通讯和同步原理,实现用例和应用
- 一个进程间同步和通讯的 C# 框架
- 一个进程间同步和通讯的 C# 框架
- 进程/线程池/进程ID/进程间的通讯pipe/Queue/Manager/进程同步
- 进程线程的同步和通讯
- 进程同步的机制以及通讯方法
- 进程间通讯与线程间通讯
- 进程间的通讯
- 进程间的通讯
- 管道实现进程间通讯
- 管道实现进程间通讯
- SenndMessage实现进程间通讯
- [LeetCode] Subsets II
- SpringMVC 3.1下返回json时中文显示乱码问题的解决方案
- success和error方法的提示信息中文乱码
- CDN(内容分发网络)
- Android ListView 点击单选State
- 进程间通讯与同步的实现
- Cookie有数量和大小的限制
- Android Touch事件分发过程详解
- 【Unity Shader实战】卡通风格的Shader(二)
- 2015年8月4日总结
- Swift工程中引用OC文件
- 支付宝支付--手机支付
- Spring 总结(一)
- struts2的核心和工作原理