📅  最后修改于: 2023-12-03 15:12:36.168000             🧑  作者: Mango
GATE CS 2012 第65章包括了关于操作系统中进程同步和通信的知识。这些是操作系统中非常重要的话题,因为它们帮助多个进程在共享的资源上协作,并且可以避免进程之间的竞争条件和死锁等问题。
在本章中,你将学习进程同步的基础知识,包括信号量和管程。你还将了解进程间通信的不同方法,如共享内存、消息队列和管道等。
信号量是一种在进程之间同步和通信的基本机制。它本质上是一个计数器,用于跟踪可用资源的数量。当进程需要访问共享资源时,它会尝试减少信号量的计数器,并在资源不可用时阻塞。当资源变得可用时,它将增加信号量的计数器并唤醒等待进程。
下面是一个简单的使用信号量的示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
int main() {
key_t key = ftok("/tmp", 'A');
int semid = semget(key, 1, 0666 | IPC_CREAT);
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1; // Wait for the semaphore
sb.sem_flg = 0;
semop(semid, &sb, 1);
printf("Semaphore acquired\n");
semctl(semid, 0, IPC_RMID); // Remove the semaphore
return 0;
}
管程是一种高级的进程同步机制,它将共享资源和同步逻辑封装在一起。通过使用管程,程序员可以更轻松地编写并发代码,并减少竞争条件和死锁的可能性。
下面是一个简单的使用管程的示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
typedef struct {
int value;
pthread_mutex_t mutex;
pthread_cond_t cond;
} counter_t;
void *increment(void *arg) {
counter_t *counter = (counter_t *)arg;
pthread_mutex_lock(&counter->mutex);
counter->value++;
pthread_cond_signal(&counter->cond);
pthread_mutex_unlock(&counter->mutex);
return NULL;
}
int main() {
counter_t counter = {0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
pthread_t th1, th2;
pthread_create(&th1, NULL, increment, &counter);
pthread_create(&th2, NULL, increment, &counter);
pthread_mutex_lock(&counter.mutex);
while (counter.value < 2) {
pthread_cond_wait(&counter.cond, &counter.mutex);
}
pthread_mutex_unlock(&counter.mutex);
printf("Counter value: %d\n", counter.value);
return 0;
}
共享内存是一种让进程之间共享内存的机制。它允许多个进程向同一段内存写入数据,并可以避免复制数据所带来的开销。
一个简单的使用共享内存的示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
int main() {
key_t key = ftok("/tmp", 'A');
int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
char *ptr = (char *)shmat(shmid, NULL, 0);
sprintf(ptr, "Hello, world!");
printf("%s\n", ptr);
shmdt(ptr);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
消息队列是一种让进程之间通过消息传递通信的机制。它允许多个进程向同一队列发送和接收消息,并可以避免数据竞争和死锁等问题。
一个简单的使用消息队列的示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h>
typedef struct {
long type;
char text[1024];
} msg_t;
int main() {
key_t key = ftok("/tmp", 'A');
int msqid = msgget(key, 0666 | IPC_CREAT);
msg_t msg = {1, "Hello, world!"};
msgsnd(msqid, &msg, sizeof(msg.text), 0);
msg_t recv;
msgrcv(msqid, &recv, sizeof(recv.text), 1, 0);
printf("%s\n", recv.text);
msgctl(msqid, IPC_RMID, NULL);
return 0;
}
管道是一种让进程之间通过管道通信的机制。它允许一个进程向管道写入数据,而另一个进程则从管道中读取数据。
一个简单的使用管道的示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int fd[2];
if (pipe(fd) == -1) {
perror("pipe");
exit(1);
}
if (fork() == 0) { // Child process
close(fd[0]);
write(fd[1], "Hello, world!", 13);
exit(0);
} else { // Parent process
close(fd[1]);
char buf[1024];
read(fd[0], buf, 1024);
printf("%s\n", buf);
exit(0);
}
}
本章介绍了进程同步和通信的基础知识,包括信号量、管程、共享内存、消息队列和管道等机制。掌握这些知识对于编写高效、可靠的并发代码至关重要。