LINUX 实现两个进程之间的通信

时间:2020-12-04 20:15:23

使用fork创建进程,实现两个进程之间的通信,一个进程把一个变量的值加5,另一个进程输出该变量的值。


sem_t:C语言中,信号量的数据类型为结构sem_t,它本质上是一个长整型的数。 

函数sem_init (sem_t *sem, int pshared, unsigned int value) 这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。如果 pshared的值是0,就表示它是当前进程的局部信号量;否则,其它进程就能够共享这个信号量。只对不让进程共享的信号量感兴趣。(这个参数受版本影响), Linux线程一般不支持进程间共享信号量,pshared传递一个非零将会使函数返回ENOSYS错误。
函数sem_post( sem_t *sem )用来增加信号量的值当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不再阻塞,选择机制同样是由线程的调度策略决定的。
函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。
函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
函数sem_destroy(sem_t *sem)用来释放信号量sem。

mmap():mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。 

mmap()系统调用形式如下: 
  void* mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset ) 
  参数fd为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信)。len是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。prot 参数指定共享内存的访问权限。可取如下几个值的或:PROT_READ(可读) , PROT_WRITE (可写), PROT_EXEC (可执行), PROT_NONE(不可访问)。flags由以下几个常值指定:MAP_SHARED , MAP_PRIVATE , MAP_FIXED,其中,MAP_SHARED , MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。offset参数一般设为0,表示从文件头开始映射。参数addr指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。函数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。

int munmap( void * addr, size_t len ) 
  该调用在进程地址空间中解除一个映射关系,addr是调用mmap()时返回的地址,len是映射区的大小。当映射关系解除后,对原来映射地址的访问将导致段错误发生。 


#include <bits/stdc++.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/mman.h>
using namespace std;
int *cnt;
sem_t *m1=NULL,*m2=NULL;

int main()
{
    m1=(sem_t*)mmap(NULL,sizeof(sem_t),PROT_READ|PROT_WRITE,MAP_ANON|MAP_SHARED,-1,0);
    m2=(sem_t*)mmap(NULL,sizeof(sem_t),PROT_READ|PROT_WRITE,MAP_ANON|MAP_SHARED,-1,0);
    cnt=(int*)mmap(NULL,sizeof(int), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1,0);
    sem_init(m1,1,1);
    sem_init(m2,1,0);
    *cnt=5;
    if(fork()){
        for(int i=0;i<10;i++){
            sem_wait(m2);
            cout<<"cnt="<<*cnt<<endl;
            sem_post(m1);
        }

    }else{
        for(int i=0;i<10;i++){
            sem_wait(m1);
            cout<<"add 5"<<endl;
            *cnt+=5;
            sem_post(m2);
        }
        return 0;
    }
    sem_destroy(m1);
    sem_destroy(m2);
    munmap(m1,sizeof(sem_t));
    munmap(m2,sizeof(sem_t));
    munmap(cnt,sizeof(int));
    return 0;
}