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

使用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;
}


  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
管道是一种进程通信(IPC)机制,在Linux系统下非常常见。下面是一个简单的例子演示如何利用管道实现两个进程之间通信: ```c #include <stdio.h> #include <unistd.h> #include <string.h> int main() { int fd[2]; char buf[100]; // 创建管道 if(pipe(fd) == -1) { perror("pipe"); return -1; } pid_t pid = fork(); if(pid == -1) { perror("fork"); return -1; } else if(pid == 0) { // 子进程 close(fd[1]); // 子进程关闭写端 while(1) { memset(buf, 0, sizeof(buf)); read(fd[0], buf, sizeof(buf)); // 从管道中读取数据 printf("child process received: %s", buf); } } else { // 父进程 close(fd[0]); // 父进程关闭读端 while(1) { printf("please input a message: "); fgets(buf, sizeof(buf), stdin); // 从标准输入读取数据 write(fd[1], buf, strlen(buf)); // 向管道中写入数据 } } return 0; } ``` 在这个例子中,我们使用`pipe()`函数创建了一个管道,然后通过`fork()`函数创建了一个子进程和一个父进程。子进程和父进程各自关闭了不需要的文件描述符,然后通过`read()`和`write()`函数在管道中进行数据的读写。父进程从标准输入读取数据,然后写入管道,子进程从管道读取数据并输出到终端上。这样就实现两个进程之间的简单通信。 需要注意的是,管道有一定的容量限制,当管道被写满时,写入操作将会阻塞,直到读取了部分数据才能继续写入;同样,当管道为空时,读取操作也会阻塞,直到有新的数据写入才能继续读取。因此,在实际使用管道进行通信时,需要注意数据的读写顺序,以及需要设置合适的缓冲区大小,避免出现阻塞等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值