Linux C语言两个进程实现通信,一个进程循环从终端输入,另一个进程循环打印,当输入quit时结束。用共享内存加信号灯集实现
时间: 2023-07-18 19:48:01 浏览: 147
好的,让我来解答你的问题。
实现两个进程之间的通信,可以使用共享内存和信号灯集。共享内存是一种让多个进程可以访问同一块内存的机制,而信号灯集则可以用来对共享内存进行同步。
以下是实现过程:
1. 创建共享内存和信号灯集
首先,我们需要创建一个共享内存和一个信号灯集。我们可以使用shmget函数和semget函数来创建它们:
```
int shmid = shmget(IPC_PRIVATE, sizeof(char) * 1024, IPC_CREAT | 0666);
char *shared_memory = (char *)shmat(shmid, NULL, 0);
int semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
```
这里我们创建了一个大小为1024的字符型共享内存区域和一个信号灯集,其中semget函数的第二个参数表示信号灯集中的信号灯数量,这里只需要一个。
2. 初始化信号灯
接下来,我们需要对信号灯进行初始化。我们可以使用semctl函数来完成:
```
union semun {
int val;
struct semid_ds *buf;
ushort *array;
};
union semun sem_union;
sem_union.val = 1;
if (semctl(semid, 0, SETVAL, sem_union) == -1) {
perror("Error initializing semaphore");
exit(EXIT_FAILURE);
}
```
这里我们将信号灯的值初始化为1,表示可以访问共享内存区域。
3. 创建子进程
接下来,我们需要创建两个子进程,一个用来从终端输入,一个用来打印共享内存区域中的内容。我们可以使用fork函数来创建子进程:
```
pid_t pid = fork();
if (pid == -1) {
perror("Error forking process");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// 子进程1,用来从终端输入
// ...
} else {
pid_t pid2 = fork();
if (pid2 == -1) {
perror("Error forking process");
exit(EXIT_FAILURE);
} else if (pid2 == 0) {
// 子进程2,用来打印共享内存区域中的内容
// ...
} else {
// 父进程
// ...
}
}
```
这里我们使用了两次fork函数来创建两个子进程,如果fork函数返回0,则表示是子进程,否则是父进程。
4. 子进程1读取终端输入并写入共享内存
在子进程1中,我们需要循环读取终端输入,并将输入的内容写入共享内存区域。我们可以使用fgets函数来读取终端输入:
```
while (1) {
printf("Please input: ");
fgets(shared_memory, 1024, stdin);
sembuf sem_buffer = {0, -1, 0};
semop(semid, &sem_buffer, 1);
if (strcmp(shared_memory, "quit\n") == 0) {
break;
}
sem_buffer.sem_op = 1;
semop(semid, &sem_buffer, 1);
}
```
这里我们使用了sembuf结构体和semop函数来对信号灯进行操作,当写入共享内存时,我们需要将信号灯的值减1,表示共享内存区域被占用,当写入完成后,我们需要将信号灯的值加1,表示共享内存区域可以被其他进程访问。
5. 子进程2循环读取共享内存并打印
在子进程2中,我们需要循环读取共享内存区域中的内容,并将其打印到终端上。我们可以使用printf函数来完成:
```
while (1) {
sembuf sem_buffer = {0, -1, 0};
semop(semid, &sem_buffer, 1);
printf("Received: %s", shared_memory);
sem_buffer.sem_op = 1;
semop(semid, &sem_buffer, 1);
if (strcmp(shared_memory, "quit\n") == 0) {
break;
}
}
```
这里我们需要先将信号灯的值减1,表示我们要读取共享内存区域中的内容,读取完成后,我们需要将信号灯的值加1,表示共享内存区域可以被其他进程访问。
6. 父进程等待子进程结束并删除共享内存和信号灯
在父进程中,我们需要等待两个子进程结束,并删除共享内存和信号灯。我们可以使用wait函数来等待子进程结束:
```
waitpid(pid, NULL, 0);
waitpid(pid2, NULL, 0);
```
等待子进程结束后,我们可以使用shmctl函数和semctl函数来删除共享内存和信号灯:
```
shmdt(shared_memory);
shmctl(shmid, IPC_RMID, NULL);
semctl(semid, 0, IPC_RMID, sem_union);
```
这里我们使用了shmdt函数将共享内存从进程中分离,然后使用shmctl函数将其删除。对于信号灯集,我们使用semctl函数将其删除。
以上就是使用共享内存和信号灯集实现两个进程通信的过程。希望能对你有所帮助!
阅读全文