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内核剖析(七)缩略图 Linux进程间通信的几种方式总结--linux内核剖析(七)](https://www.72715.net/wp-content/uploads/2023/05/63440fb29c43a39543938c7b4679cbfb.png)
#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