轻松掌握IPC技巧,读懂Linux进程间通信(一)

由于现代操作系统中,进程间都是地址空间隔离的,每一个进程都有独立的地址空间,而我们的业务软件为了良好的架构和运维都会进行模块化设计,IPC进程间通信是一个必须要掌握的技能。进程间通信(IPC)是指在不同进程之间传递数据或信号的一系列方法。进程间通信有很多种方式,每种方式都会有自己的特点。

轻松掌握IPC技巧,读懂Linux进程间通信(一)

在Linux系统中,IPC包括多种机制,主要有管道(Pipes)、信号(Signals)、消息队列(Message Queues)、共享内存(Shared Memory)和信号量(Semaphores)、套接字(socket)、内存映射等,今天先介绍前四种。

1. 管道(Pipes)

管道是最简单的IPC形式。我们可以把它想象成一个数据流水线,一个进程在管道的一端放入数据,另一个进程从另一端取出数据。管道分为匿名管道和命名管道。

轻松掌握IPC技巧,读懂Linux进程间通信(一)

  • 匿名管道是临时的,通常用于父子进程间的通信。
#include <stdio.h>
#include <unistd.h>

int main() {
    int pipefd[2];
    pid_t cpid;
    char buf;
    
    if (pipe(pipefd) == -1) {
        perror("pipe");
        return 1;
    }
    
    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        return 1;
    }
    
    if (cpid == 0) {    // 子进程
        close(pipefd[1]); // 关闭写端
        while (read(pipefd[0], &buf, 1) > 0) {
            write(STDOUT_FILENO, &buf, 1);
        }
        write(STDOUT_FILENO, "n"1);
        close(pipefd[0]);
        _exit(0);
    } else {            // 父进程
        close(pipefd[0]); // 关闭读端
        write(pipefd[1], "Hello, World!"13);
        close(pipefd[1]);
        wait(NULL);
        return 0;
    }
}
  • 命名管道(FIFO)是一种特殊文件类型,在文件系统中有对应的文件名。可以用于不相关进程间的通信。
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int main() {
    int fd;
    char *myfifo = "/tmp/myfifo";
    mkfifo(myfifo, 0666); // 创建命名管道

    char arr1[80], arr2[80];
    // 写入数据
    fd = open(myfifo, O_WRONLY);
    fgets(arr2, 80stdin);
    write(fd, arr2, sizeof(arr2));
    close(fd);

    // 读取数据
    fd = open(myfifo, O_RDONLY);
    read(fd, arr1, sizeof(arr1));
    printf("User2: %sn", arr1);
    close(fd);

    return 0;
}

2. 信号(Signals)轻松掌握IPC技巧,读懂Linux进程间通信(一)

信号是一种较为简单的通信方式,用于通知接收进程某个事件已经发生。以下是一个捕获SIGINT(通常由Ctrl+C产生)的例子:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sigint_handler(int sig) {
    write(1"Caught SIGINT!n"15);
}

int main() {
    signal(SIGINT, sigint_handler);
    while (1) {
        sleep(1);
    }
    return 0;
}

3. 消息队列(Message Queues)

消息队列允许一个或多个进程向它写入消息,然后由另一个进程读取。这些消息存储在内核中,并按照顺序发送。

轻松掌握IPC技巧,读懂Linux进程间通信(一)

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

struct my_msg {
    long msg_type;
    char msg_text[100];
};

int main() {
    key_t key = ftok("ipcfile"65); // 创建唯一的key
    int msgid = msgget(key, 0666 | IPC_CREAT); // 创建消息队列
    struct my_msg message;

    message.msg_type = 1;
    printf("Write Data : ");
    fgets(message.msg_text, sizeof(message.msg_text), stdin);

    msgsnd(msgid, &message, sizeof(message), 0); // 发送消息

    printf("Data send is : %s n", message.msg_text);
    return 0;
}

4. 共享内存(Shared Memory)

共享内存是最快的IPC方式,因为进程是直接对内存进行访问。但是,由于多个进程可以同时访问,因此需要使用信号量进行同步。

轻松掌握IPC技巧,读懂Linux进程间通信(一)

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main() {
    key_t key = ftok("shmfile",65);
    int shmid = shmget(key,1024,0666|IPC_CREAT);
    char *str = (char*) shmat(shmid,(void*)0,0);

    printf("Write Data : ");
    gets(str);

    printf("Data written in memory: %sn",str);
    
    shmdt(str);
    return 0;
}

在实际应用中,选择哪种IPC机制取决于具体需求,如数据的大小、传输速度、同步与异步等。每种机制都有其适用场景和优缺点。在设计系统时,需要根据实际场景和需求进行合理选择。

推荐一本开发者必备的经典手册,Linux编程资深专家Michael Kerrisk在书中详细描述了Linux/UNIX系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。《Linux/UNIX系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾200个程序示例,另含88张表格和115幅示意图。轻松掌握IPC技巧,读懂Linux进程间通信(一)

公众号后台回复“linux编程手册”获取下载链接


轻松掌握IPC技巧,读懂Linux进程间通信(一)

点个在看你最好看

轻松掌握IPC技巧,读懂Linux进程间通信(一)

原文始发于微信公众号(计算机刨根问底):轻松掌握IPC技巧,读懂Linux进程间通信(一)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/207781.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!