Linux进程间通信编程记录(一)

一、进程间通信概述

1.进程间通信:IPC(InterProcess Communication)

2.单机通信:一台电脑上的通信

3.多机通信:多台电脑上的通信,是基于网络的通信

4.单机通信类型: 半双工管道 (FIFO),全双工管道 (命名全双工管道),消息队列,信号量,共享内存

5.多机通信类型:嵌套字,STREAMS,Socket

二、管道通信原理

1.管道:通常指无名管道

2.特点:

(1).半双工,即数据只能在一个方向上流动,具有固定的读端和写段

(2).只能用于进程间的通信

(3).可看做一种特殊的存在于内存的文件,write,read等系统函数可对它进行操作

3.原形:

int pipe(int fd[2]);//建立管道,失败返回-1,成功返回0

fd[0]:读

fd[1]:写

4.用法:

读时,关闭写

写时,关闭读

三、管道编程之无名管道

int main(){
        int fd[2];
        pid_t repid;
        char buf[128];
        int repipe=pipe(fd);//创建无名管道
        if(repipe < 0){
                printf("creat unamed pipe failt\n");
        }
        repid=fork();//创建进程

        if(repid < 0){
                printf("creat fork failt\n");
        }
        else if(repid > 0){
                sleep(3);//等待3秒便于观察父子进程
                printf("this is father fork\n");
                close(fd[0]);//关闭可读通道
                write(fd[1],"you are a lucky dog",strlen("you are a lucky dog"));//往可写通道里写入内容
                wait(NULL);//让子进程先执行
        }
        else{
                printf("this is child fork\n");
                close(fd[1]);//关闭可写通道
                read(fd[0],buf,128);//读取可写通道内容
                printf("readBuf=%s\n",buf);
                exit(0);//正常退出
        }
        return 0;
}

运行结果:

四、管道编程之有名管道

1. FIFO:命名管道,也是这一种文件类型

2.特点:无关进程之间的数据交换,有路径名与之关联

3.原形:

int mkfifo(const char *pathname,mode_t mode);//成功返回0,反之-1

4.代码实现:

int main(){

        int fifo=mkfifo("./file",0600);//建立实名管道并设置权限
        if(fifo == -1 && errno != EEXIST){//errno,错误;EEXIST,如果创建的管道存在则会返回EEXIST
                printf("creat fifo fault!\n");
        }
        return 0;
}

五、有名管道数据通信实现

1.实现管道的读取内容:

//       int mkfifo(const char *pathname, mode_t mode);
//       int open(const char *pathname, int flags);
//       ssize_t read(int fd, void *buf, size_t count);
int main(){
        char readBuf[40];
        int n_read;
        int cnt=0;
        int fifo=mkfifo("./file",0600);//创建有名管道并设置权限
        if(fifo == -1 && errno != EEXIST){
                printf("creat fifo fault!\n");
        }
        int fd=open("./file",O_RDONLY);//打开管道,并设置为只读
        if(fd != -1){
                printf("open file success!\n");
        }
        while(1){
                n_read=read(fd,readBuf,40);//读取写入的内容
                sleep(1);
                printf("return value:%d,readBuf=%s\n",n_read,readBuf);
                cnt++;
                if(cnt==5){
                        break;
                }
        }
        close(fd);//关闭文件
        return 0;
}

2.实现管道的写入内容 :

int main(){
        int cnt=0;
        int n_write;
        char* str="you are a lucky dog";
        int fd=open("./file",O_WRONLY);
        while(1){
                n_write=write(fd,str,strlen(str));//写入内容
                cnt++;
                if(cnt==5){//控制写入的次数
                        break;
                }
        }
        if(n_write != -1){
                printf("write success!\n");
        }
        close(fd);//关闭文件
        return 0;
}

3.运行结果

六、消息队列通信原理

1.消息队列:即消息的链表,存放于内核中,每一个消息队列都有一个标识符

2.特点:

(1).消息队列是面向记录,具有特定的格式及优先级

(2).独立的接受与发送。进程终止时,消息队列不会被删除

(3).可以实现随机查询,可以按消息的类型读取

3.原形:

int msgget(key_t key,int flag);//创建或打开消息队列,成功返回ID,反之-1

int msgsnd(ind msgid,const void *ptr,size_t size,int flag);//发送消息,成功返回0,反之-1

int msgrcv(int msgid,void *ptr,size_t size,long type,long flag);//读取消息,成功返回消息长度,反之-1

int msgctl((int msgid,int cmd,struct msgid_ds *buf);//控制消息队列,成功返回0 ,反之-1

4.参数功能:

从标识符为msgid的消息队列里接收一个指定类型的消息 并 存储于msgp中 读取后 把消息从消息队列中删除
msgtyp:为 0 表示无论什么类型 都可以接收
msgp:存放消息的结构体
msgsz:要接收的消息的大小 不包含消息类型占用的4字节
msgflg:如果是0 标识如果没有指定类型的消息 就一直等待,如果是IPC_NOWAIT 则表示不等待

七、消息队列收发数据与移除

代码实现1:

typedef struct msgbuf {
       long mtype;
       char mtext[80];
}msgs;

//key_t ftok(const char *pathname, int proj_id);
//int msgctl(int msqid, int cmd, struct msqid_ds *buf);

int main(){
        key_t key;//键值
        key=ftok(".",1);
        printf("key=%x\n",key);//%x 转化为16进制
        msgs readBuf;
        msgs sendBuf={998,"dugad is a handsome man"};
        int msgId=msgget(key,IPC_CREAT|0777);//创建消息队列,成功返回0,反之-1,并设置权限
        if(msgId == -1){//判断是否创建成功
                printf("get msg failure\n");
        }
        int receive=msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),888,0);//接受消息队列
        if(receive == -1){//判断是否接受成功
                printf("readBuf errno!\n");
        }
        else{
                printf("readBuf success!\n");
        }
        int send=msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);//发送消息
        if(send == -1){//判断是否发送成功
                printf("sendBuf errno!\n");
        }
        else{
                printf("sendBuf success!\n");
        }
        printf("readBuf=%s\n",readBuf.mtext);//打印接受的内容
        int n_msgctl= msgctl(msgId,IPC_RMID,NULL);//清除消息队列
        printf("n_msgctl=%d\n",n_msgctl);
        if(n_msgctl == -1){//判断是否清除成功
                printf("remove msg errno!\n");
        }
        else{
                printf("remove msg success!\n");
        }
        return 0;
}

代码实现2:

typedef struct msgbuf {
       long mtype;
       char mtext[80];
}msgs;

int main(){
        key_t key;
        key=ftok(".",1);
        printf("key=%x\n",key);
        msgs sendBuf={888,"this magsnd from quer"};
        msgs readBuf;
        int msgId=msgget(key,IPC_CREAT|0777);//创建消息队列,成功返回0,反之-1,并设置权限

        if(msgId == -1){
                printf("get msg failure\n");
        }

        int send=msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);
        if(send == -1){
                printf("msgsend errno!\n");
        }
        else{
                printf("magsend success!\n");
        }
        int receive=msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),998,0);
        if(receive == -1){
                printf("readBuf errno!\n");
        }
        else{
                printf("readBuf success!\n");
        }
        printf("readBuf=%s\n",readBuf.mtext);
        int n_msgctl=msgctl(msgId,IPC_RMID,NULL);
        printf("n_msgctl=%d\n",n_msgctl);
        if(n_msgctl == -1){
                printf("remove msg errno!\n");
        }
        else{
                printf("remove msg success!\n");
        }
        return 0;
}

运行结果:

注意:

在读写完成后删除消息队列时,只需在其中一方设置删除即可,如果两边都设置了删除消息队列会使,有一方会删除失败

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值