进程通信

https://blog.csdn.net/wh_sjc/article/details/70283843

1.无名管道

1.1 管道大多数为半双工通信 

1.2 管道只能在具有公共祖先的两个进程中使用,通常,一个管道由一个进程创建,在进程调用fork之后,这个管道就能在父子进程中通信

1.3 管道通过pipe调用的  int pipe(int fd[2])

fd[0] 表示读 fd[1] 表示写 ,由于半双工通信机制,一个进程读的时候关闭写,写的时候关闭读

#include "apue.h"
int main()
{
        int n;
        int fd[2];
        pid_t pid;
        char line[MAXLINE];

        if(pipe(fd)<0)
                err_sys("pipe error");
        if ((pid = fork())<0)
                {
                        err_sys("fork error");
                }
        else if (pid>0)
        {
                close(fd[0]);
                write(fd[1],"hello world\n",12);
        }
        else
        {
                close(fd[1]);
                n = read(fd[0],line,MAXLINE);
                write(STDOUT_FILENO,line,n);
        }
        exit(0);
}


result:
hello world

2 命名管道 FIFO

2.1 无名进程只能在两个相关的进程间通信,有名管道在不相关的进程中也能通信

2.2 示例

pipe_read.sh 输出管道内容

pipe_write.sh 向管道中写入内容

pipe_read.sh:


if [ ! -p /tmp/pipe1 ];then
        cd /etc
        mknod /tmp/pipe1 p
fi
while :
do
        read msg
        if [ "$msg" = "" ];then
                continue
        else
                echo $msg
        fi
done </tmp/pipe1


pipe_write.sh:

while :
do
        echo "Enter your name: \c"
        read name
        today=`date`
        echo "$name  $today" >/tmp/pipe1
 done

结果:

区别:

从结构上看,无名管道没有文件路径名,不占用文件目录项,因此文件目录结构中的链表不适用于这种文件,它只是存在于打开文件结构中的一个临时文件,随其所依附的进程的生存而生存,当进程终止时,无名管道也随之消亡送入管道的信息一旦被读进程取用就从管道中消失了,读写操作之间符合先进先出的队列原则(有名管道也是)。有名管道类似文件,除非主动删除,否则一直存在。

3.消息队列

3.1简介

消息队列是消息的链接表,存储在内核中,由消息队列标识符标识。msgget创建或者打开一个队列,msgsnd将新消息添加到队列尾端

3.2 消息队列特点

1.管道只能依照先进先出的顺序通信,消息队列还可以按照消息的类型字段取消息

2.消息队列独立于消息发送或者接收进程,进程结束,消息队列及其内容不会被删除

3. msgsnd(msqid, &msg, sizeof(msg.mtext), 0); 发送消息

   msgrcv(msqid, &msg, 256, 999, 0);  接收消息  

msg_service.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>

// 用于创建一个唯一的key
#define MSG_FILE "/etc/passwd"

// 消息结构
struct msg_form {
    long mtype;
    char mtext[256];
};

int main()
{
    int msqid;
    key_t key;
    struct msg_form msg;

    // 获取key值
    if((key = ftok(MSG_FILE,'z')) < 0)
    {
        perror("ftok error");
        exit(1);
    }

    // 打印key值
    printf("Message Queue - Server key is: %d.\n", key);

    // 创建消息队列
    if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
    {
        perror("msgget error");
        exit(1);
    }

    // 打印消息队列ID及进程ID
    printf("My msqid is: %d.\n", msqid);
    printf("My pid is: %d.\n", getpid());

    // 循环读取消息
    for(;;)
    {
        msgrcv(msqid, &msg, 256, 888, 0);// 返回类型为888的第一个消息
        printf("Server: receive msg.mtext is: %s.\n", msg.mtext);
        printf("Server: receive msg.mtype is: %d.\n", msg.mtype);

        msg.mtype = 999; // 客户端接收的消息类型
        sprintf(msg.mtext, "hello, I'm server %d", getpid());
        msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
    }
    return 0;
}

msg_client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>

// 用于创建一个唯一的key
#define MSG_FILE "/etc/passwd"

// 消息结构
struct msg_form {
    long mtype;
    char mtext[256];
};

int main()
{
    int msqid;
    key_t key;
    struct msg_form msg;

    // 获取key值
    if ((key = ftok(MSG_FILE, 'z')) < 0)
    {
        perror("ftok error");
        exit(1);
    }

    // 打印key值
    printf("Message Queue - Client key is: %d.\n", key);

    // 打开消息队列
    if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
    {
        perror("msgget error");
        exit(1);
    }

    // 打印消息队列ID及进程ID
    printf("My msqid is: %d.\n", msqid);
    printf("My pid is: %d.\n", getpid());

    // 添加消息,类型为888
    msg.mtype = 888;
    sprintf(msg.mtext, "hello, I'm client %d", getpid());
    msgsnd(msqid, &msg, sizeof(msg.mtext), 0);

    // 读取类型为777的消息
    msgrcv(msqid, &msg, 256, 999, 0);
    printf("Client: receive msg.mtext is: %s.\n", msg.mtext);
    printf("Client: receive msg.mtype is: %d.\n", msg.mtype);
    return 0;
}

4.信号量

信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

5.共享内存

5.1 特点

     1.共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。

     2.因为多个进程可以同时操作,所以需要进行同步。

     3.信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值