Linux系统实现两进程之间的通信

需求介绍

实现两个进程间的通信,一个进程从键盘输入字符串,发送给另一个进程。接收进程将该字符串逆序,并输出相应的结果。

简单介绍

  1. fork()用于创建新进程

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

  3. sem_init (sem_t *sem, int pshared, unsigned int value)
    这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。如果 pshared的值是0,就表示它是当前进程的局部信号量;否则,其它进程就能够共享这个信号量。只对不让进程共享的信号量感兴趣。(这个参数受版本影响), Linux线程一般不支持进程间共享信号量,pshared传递一个非零将会使函数返回ENOSYS错误。

  4. sem_post( sem_t *sem )用来增加信号量的值当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不再阻塞,选择机制同样是由线程的调度策略决定的。

  5. sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。

  6. sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。

  7. sem_destroy(sem_t *sem)用来释放信号量sem。

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

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


代码

#include <bits/stdc++.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <unistd.h>
#include <pthread.h>
#include <string>

using namespace std;


// 消息
char* msg;

// 定义两个信号量
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);
    msg=(char*)mmap(NULL,sizeof(char), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1,0);
    sem_init(m1,1,1);  //对信号量进行初始化
    sem_init(m2,1,0);
    
    if(fork()){  //fork用于创建进程
        //以下基本就是操作系统进程通信的信号量一些简单算法了,不多说了
        for(int i=0;i<10;i++){
            sem_wait(m2);
            cout<<"请发送数据:";
            cin>>msg;
            sem_post(m1);
        }

    }else{
        for(int i=0;i<10;i++){
            sem_wait(m1);
            string str = msg;
            reverse(str.begin(),str.end());
            cout<<"接受到的数据逆序:"<<str<<endl;
            sem_post(m2);
        }
        return 0;
    }
    
    sem_destroy(m1);
    sem_destroy(m2);
    munmap(m1,sizeof(sem_t));
    munmap(m2,sizeof(sem_t));
    return 0;
}


运行

  1. 创建一个thread_msg2.cpp文件,将代码写入

  2. 进行编译

    g++ -g thread_msg2.cpp -o thread_msg2  -pthread
    

    可能需要下载安装一下:yum install -y gcc-c++

  3. 运行

    ./thread_msg2
    
  4. 结果
    在这里插入图片描述

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值