linux基础---进程间的通信《五》

进程间的通信:
IPC(InterProcess Communication )进程间的通信,通过内核提供的缓冲区进行

常见的通信方式:
单工(广播),半双工(对讲机),全双工(打电话)
管道:半双工
在这里插入图片描述

pipe通信
在这里插入图片描述
在这里插入图片描述
成功返回0,失败返回-1. fd[0]代表读端,fd[1]代表写端

读函数read
ssize_t read(int fd,void *buf,size_t nbyte)
read函数是负责从 fd中读取内容到buf中.成功时,read返回实际所读的字节数,如果返回的值是0,表示已经读到文件的结束了.
小于0表示出现了错误.如果错误为 EINTR说明读是由中断引起的, 如果是ECONNREST表示网络连接出了问题.
写函数write
ssize_t write(int fd,const void *buf,size_t nbytes)
write函数将buf中的nbytes字节内容写 入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量. 在网络程序中,当我们向套接字文件描述符写时有俩种可能.
1)write 的返回值大于0,表示写了部分或者是全部的数据.
2)返回的值小于0,此时出现了错误.我们要根据错误类型来处理. 如果错误为EINTR表示在写的时候出现了中断错误.
如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接).
3)nbytes 可以大于实际能写入的大小,比如,缓冲区只能写入100,但却写入1000,前100个字节能写入成功。可利用这个特性加上移动指针反复写入
在这里插入图片描述

SIGPIPT是13号信号。

计算管道的大小:512*8
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
FIFO通信
在这里插入图片描述
写:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char * argv[])
{
    if(argc != 2){
        printf("./a.out fifoname\n");
        return -1;
    }

    // 当前目录有一个 myfifo 文件
    //打开fifo文件
    printf("begin open ....\n");
    int fd = open(argv[1],O_WRONLY);
    printf("end open ....\n");
    //写
    char buf[256];
    int num = 1;
    while(1){
        memset(buf,0x00,sizeof(buf));
        sprintf(buf,"xiaoming%04d",num++);
        write(fd,buf,strlen(buf));
        sleep(1);
        //循环写
    }
    //关闭描述符
    close(fd);
    return 0;
}

读:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char *argv[])
{
    if(argc != 2){
        printf("./a.out fifoname\n");
        return -1;
    }
    printf("begin oepn read...\n");
    int fd = open(argv[1],O_RDONLY);
    printf("end oepn read...\n");

    char buf[256];
    int ret;
    while(1){
        //循环读
        memset(buf,0x00,sizeof(buf));
        ret = read(fd,buf,sizeof(buf));
        if(ret > 0){
            printf("read:%s\n",buf);
        }
    }

    close(fd);
    return 0;
}

mmap共享映射区
创建映射区:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

在这里插入图片描述
释放映射区:
在这里插入图片描述
mmap九问:
加粗样式
mmap实现父子进程通信:
用命令拷贝一个文件的头文件到另一个文件
在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>

int main()
{
    // 先创建映射区
    int fd = open("mem.txt",O_RDWR);
    //int *mem = mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    int *mem = mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0);
    if(mem == MAP_FAILED){
        perror("mmap err");
        return -1;
    }
    // fork子进程
    pid_t pid = fork();

    // 父进程和子进程交替修改数据
    if(pid == 0 ){
        //son 
        *mem = 100;
        printf("child,*mem = %d\n",*mem);
        sleep(3);
        printf("child,*mem = %d\n",*mem);
    }
    else if(pid > 0){
        //parent
        sleep(1);
        printf("parent,*mem=%d\n",*mem);
        *mem = 1001;
        printf("parent,*mem=%d\n",*mem);
        wait(NULL);
    }

    munmap(mem,4);
    close(fd);
    return 0;
}                  

匿名映射:
在这里插入图片描述
函数说明:ftruncate()会将参数fd 指定的文件大小改为参数length 指定的大小。参数fd 为已打开的文件描述词,而且必须是以写入模式打开的文件。如果原来的文件大小比参数length 大,则超过的部分会被删去。

mmap实现无血缘关系的进程通信:
如果进程要通信,flags必须设为MAP_SHARED
写:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>

typedef struct  _Student{
    int sid;
    char sname[20];
}Student;

int main(int argc,char *argv[])
{
    if(argc != 2){
        printf("./a.out filename\n");
        return -1;
    }

    // 1. open file 
    int fd = open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0666);
    int length = sizeof(Student);

    ftruncate(fd,length);

    // 2. mmap
    Student * stu = mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

    if(stu == MAP_FAILED){
        perror("mmap err");
        return -1;
    }
    int num = 1;
    // 3. 修改内存数据
    while(1){
        stu->sid = num;
        sprintf(stu->sname,"xiaoming-%03d",num++);
        sleep(1);//相当于没隔1s修改一次映射区的内容
    }
    // 4. 释放映射区和关闭文件描述符
    munmap(stu,length);
    close(fd);

    return 0;
}
~      

读:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>

typedef struct _Student{
    int sid;
    char sname[20];
}Student;

int main(int argc,char *argv[])
{
    //open file 
    int fd = open(argv[1],O_RDWR);
    //mmap 
    int length = sizeof(Student);
    Student *stu = mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if(stu == MAP_FAILED){
        perror("mmap err");
        return -1;
    }
    //read data 
    while(1){
        printf("sid=%d,sname=%s\n",stu->sid,stu->sname);
        sleep(1);
    }
    //close and munmap 
    munmap(stu,length);
    close(fd);
    return 0;
}

~    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值