进程通讯
- 内存共享
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 100
int 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
版权声明:本文为博主原创文章,未经博主允许不得转载。