Linux进程间通信的几种方式总结--linux内核剖析(七)

if (pipe(fd) == -1) {perror("pipe");exit(EXIT_FAILURE);if (pid == -1) {perror("fork");

在Linux操作系统中,进程间通信是非常重要的一部分。不同进程之间需要相互协作、共享资源、传递信息等。因此,了解并掌握不同的进程间通信方式是非常必要的。

本文将对Linux内核中常见的几种进程间通信方式进行总结和介绍。这些方式包括管道、消息队列、共享内存、信号量和套接字。

管道

管道是一种最简单也最基础的进程间通信机制。它可以实现父子进程之间或者兄弟进程之间的数据传输。

在Linux中,我们可以使用pipe()函数来创建一个管道,并通过fork()函数创建出子进程和父进程来实现数据传输。

下面是一个简单示例代码:

“`

#include

#include

#include

#define MSG_SIZE 16

int main()

{

int fd[2];

char msg[MSG_SIZE] = “Hello, world!n”;

if (pipe(fd) == -1) {

perror(“pipe”);

exit(EXIT_FAILURE);

}

pid_t pid = fork();

if (pid == -1) {

perror(“fork”);

} else if (pid == 0) { // 子进程

close(fd[1]);

read(fd[0], msg, MSG_SIZE);

printf(“Child process received message: %s”, msg);

} else { // 父进程

close(fd[0]);

write(fd[1], msg, MSG_SIZE);

printf(“Parent process sent message: %s”, msg);

return 0;

}

消息队列

消息队列是一种进程间通信机制,它可以实现不相关的进程之间的数据传输。

在Linux中,我们可以使用msgget()函数创建一个消息队列,并使用msgsnd()和msgrcv()函数向消息队列发送和接收信息。

#include

#include

struct my_msgbuf {

long mtype;

char mtext[MSG_SIZE];

};

key_t key = ftok(“.”, ‘a’);

int msqid;

if ((msqid = msgget(key, 0644 | IPC_CREAT)) == -1) {

perror(“msgget”);

struct my_msgbuf buf;

buf.mtype = 1;

char msg[MSG_SIZE] = “Hello, world!n”;

strcpy(buf.mtext, msg);

if (msgsnd(msqid, &buf, sizeof(buf.mtext), 0) == -1) {

perror(“msgsnd”);

exit(EXIT_FAILURE);

}

if (msgrcv(msqid, &buf, sizeof(buf.mtext), 1, 0) == -1) {

perror(“msgrcv”);

printf(“Received message: %s”, buf.mtext);

if (msgctl(msqid, IPC_RMID, NULL) == -1) {

perror(“msgctl”);

共享内存

共享内存是一种高效的进程间通信机制,它可以让多个进程之间共享同一块物理内存。这种方式相比于其他进程间通信方式更加快速和灵活。

在Linux中,我们可以使用shmget()函数创建一个共享内存区域,并使用shmat()函数将其映射到进程的地址空间中。此外,我们还需要使用shmdt()函数解除映射关系。

Linux进程间通信的几种方式总结--linux内核剖析(七)

#include

#define SHM_SIZE 100

int shmid;

if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) {

perror(“shmget”);

char *data;

if ((data = shmat(shmid, NULL, 0)) == (char *)-1) {

perror(“shmat”);

char msg[SHM_SIZE] = “Hello, world!n”;

strcpy(data, msg);

printf(“Received message: %s”, data);

if (shmdt(data) == -1) {

perror(“shmdt”);

exit(EXIT_FAILURE);

}

if (shmctl(shmid, IPC_RMID, NULL) == -1) {

perror(“shmctl”);

exit(EXIT_FAILURE);

信号量

信号量是一种进程间同步和互斥的机制,它可以控制多个进程对共享资源的访问。

在Linux中,我们可以使用semget()函数创建一个信号量,并使用semop()函数对其进行操作。

#include

int semid;

if ((semid = semget(key, 1, 0644 | IPC_CREAT)) == -1) {

perror(“semget”);

struct sembuf sb;

sb.sem_num = 0;

sb.sem_op = -1; // P操作

sb.sem_flg = SEM_UNDO;

if (semop(semid, &sb, 1) == -1) {

perror(“semop”);

printf(“Critical sectionn”);

sb.sem_op = 1; // V操作

}

return 0;

套接字

套接字是一种网络编程方式,它可以实现不同主机之间的进程间通信。

在Linux中,我们可以使用socket()函数创建一个套接字,并使用bind()和listen()函数来准备监听请求。此外,我们还需要使用accept()函数来接受客户端连接。

#include

#include

#include

#define PORT 8080

int server_fd, new_socket;

struct sockaddr_in address;

int opt = 1;

int addrlen = sizeof(address);

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

perror(“socket”);

if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,

&opt, sizeof(opt))) {

perror(“setsockopt”);

address.sin_family = AF_INET;

address.sin_addr.s_addr = INADDR_ANY;

address.sin_port = htons(PORT);

if (bind(server_fd, (struct sockaddr *)&address,

sizeof(address)) == -1) {

perror(“bind”);

if (listen(server_fd, 3) == -1) {

perror(“listen”);

exit(EXIT_FAILURE);

if