📜  门| GATE CS 2012 |第65章(1)

📅  最后修改于: 2023-12-03 15:12:36.168000             🧑  作者: Mango

门| GATE CS 2012 |第65章

介绍

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);
  }
}
总结

本章介绍了进程同步和通信的基础知识,包括信号量、管程、共享内存、消息队列和管道等机制。掌握这些知识对于编写高效、可靠的并发代码至关重要。