码迷,mamicode.com
首页 > 系统相关 > 详细

进程间通讯与同步的实现

时间:2015-08-04 17:22:47      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:管道   共享   同步   

进程通讯

  • 内存共享
    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

版权声明:本文为博主原创文章,未经博主允许不得转载。

进程间通讯与同步的实现

标签:管道   共享   同步   

原文地址:http://blog.csdn.net/qq285016127/article/details/47278059

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!