Linux进程通信与同步

Linux进程通信与同步

提供几种机制方便进程之间进行数据交换或者进程之间的同步

方式:

  • pipe管道
  • fifo命名管道
  • 共享内存
  • 信号量
  • socket通信

管道

  • 两个或多个进程间通过管道,可以互相传递信息,利用read和write系统调用函数来进行读写操作
  • 管道可以看作成一个文件,有两个文件描述符,分别用来读文件和写文件,但同一时刻只能一读一写,因此又称半双工通信
  • 特点是:仅适用于同一组先的进程间通信

接口代码

#include <unistd.h>

int pipe(int filedes[2]);

参数解释

  • filedes: 一个有两个成员的整形数组,用来保存管道文件描述符
    • filedes[0]: 从管道读数据
    • filedes[1]: 从管道写数据

返回值

返回值非0,表示错误

  • EMFILE: 进程使用的文件描述符过多
  • ENFILE: 系统的文件表已满
  • EFAULT: 文件描述符无效

实例代码

从管道中读文件和写文件

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int filedes[2];
    int fd;
    char *buff = "这是管道通信";

    char out[100];

    if (pipe(filedes) == 0)
    {
        fd = write(filedes[1], buff, strlen(buff));
        printf("写入%d个字符\n", fd);

        fd = read(filedes[0], out, strlen(buff));
        printf("读取%d个字节,字符串为:%s \n", fd, out);
    }
    exit(0);
}

/**
 * 运行结果
 * 写入18个字符
 * 读取18个字节,字符串为:这是管道通信
 */

子进程向管道中写数据,父进程读数据

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    int filedes[2]; // 定义管道文件描述符
    pid_t pid;
    int len;
    char some_data[1024]; // 输入缓冲区
    char buff[1024];      // 输出缓冲区

    strcpy(some_data, argv[1]);
    if (pipe(filedes) == 0)
    {
        pid = fork();
        if (pid < 0)
            printf("子进程创建失败\n");
        else if (pid == 0)
        {
            close(filedes[0]);
            len = write(filedes[1], some_data, strlen(argv[1]));
            printf("写入: %d个字节,写入字符串为: %s\n", len, argv[1]);
        }
        else
        {
            wait(NULL);
            close(filedes[1]);
            len = read(filedes[0], buff, 1024);
            printf("从管道中读取: %d个字节,字符串为: %s\n", len, buff);
        }
    }
    exit(0);
}

/**
 * 输出结果为
 * 写入: 30个字节,写入字符串为: 我是牢弟,嗨,牢大,肘击
 * 从管道中读取: 30个字节,字符串为: 我是牢弟,嗨,牢大,肘击
 */

命名管道

  • 命名管道不需要程序有一个共同祖先进程启动
  • 命名管道是一种特殊类型的文件,行为和管道类似

接口代码

以命令行的方式创建FIFO管道

mknod filename p
mkfifo filename p

程序中创建FIFO管道

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char* filename,mode_t mode);
int mknod(const char* filename,mode_t mode|S_IFIFP,(dev_t)0);

参数解释

  • filename: 要创建的文件名
  • mode: 文件的权限
  • (dev_t)0: 无实际意义,通常设置为0

返回值

  • 成功时返回 0。
  • 失败时返回 -1,并设置 errno 以指示错误原因。

实例代码

mkfifo文件

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

int main()
{
    int res = mkfifo("./mkfifo", 0777); // 创建管道文件
    if (res == 0)
        printf("命名管道创建成功\n");
    else
        perror("创建失败\n");
    exit(0);
}

mkfileRead文件

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

int main()
{
    char buff[1024] = {0};
    int fd;
    int len = 0;
    fd = open("./mkfifo", O_RDONLY, 0); // 打开管道文件
    if (fd == -1)
    {
        printf("文件打开失败\n");
        exit(1);
    }
    else
    {
        if ((len = read(fd, buff, 1024)) == -1) // 读取管道文件
        {
            printf("文件读取失败\n");
            exit(1);
        }
        else
        {
            printf("文件读取成功,读取字符数为: %d,字符串为: %s\n", len, buff);
        }
    }
    close(fd);
    exit(0);
}

mkfileWrite文件

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

int main()
{
    char buff[1024] = "写入:这里是mkfifoRead";
    int fd;
    int len = 0;
    fd = open("./mkfifo", O_WRONLY, 0); // 打开管道文件
    if (fd == -1)
    {
        printf("文件打开失败\n");
        exit(1);
    }
    else
    {
        if ((len = write(fd, buff, 1024)) == -1) // 读取管道文件
        {
            printf("文件写入失败\n");
            exit(1);
        }
        else
        {
            printf("文件写入成功,写入字符串长度为 %d,字符串为 %s\n", len, buff);
        }
    }
    close(fd);
    exit(0);
}
未完待继…
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值