将《linux c编程大全》第六章中信号量(灯)的程序照样编写一遍,完成结果分析。
时间: 2023-08-31 07:41:12 浏览: 219
### 回答1:
好的,以下是基于《Linux C编程大全》第六章中信号量(灯)的程序的代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define SEM_KEY 4001
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main(int argc, char *argv[])
{
int semid;
union semun semopts;
unsigned short sem_array[2] = {1, 1}; // 初始值为1,表示灯亮
if ((semid = semget(SEM_KEY, 2, IPC_CREAT | 0666)) == -1) { // 创建信号量集
perror("semget error");
exit(EXIT_FAILURE);
}
semopts.array = sem_array;
if (semctl(semid, 0, SETALL, semopts) == -1) { // 初始化信号量集
perror("semctl error");
exit(EXIT_FAILURE);
}
pid_t pid;
if ((pid = fork()) == -1) {
perror("fork error");
exit(EXIT_FAILURE);
} else if (pid == 0) { // 子进程
while (1) {
struct sembuf sops = {0, -1, SEM_UNDO}; // 对信号量0进行P操作
if (semop(semid, &sops, 1) == -1) {
perror("semop error");
exit(EXIT_FAILURE);
}
printf("Child process: the light is on\n");
sleep(2);
printf("Child process: the light is off\n");
sops.sem_op = 1; // 对信号量0进行V操作
if (semop(semid, &sops, 1) == -1) {
perror("semop error");
exit(EXIT_FAILURE);
}
sleep(2);
}
} else { // 父进程
while (1) {
struct sembuf sops = {1, -1, SEM_UNDO}; // 对信号量1进行P操作
if (semop(semid, &sops, 1) == -1) {
perror("semop error");
exit(EXIT_FAILURE);
}
printf("Parent process: the light is on\n");
sleep(2);
printf("Parent process: the light is off\n");
sops.sem_op = 1; // 对信号量1进行V操作
if (semop(semid, &sops, 1) == -1) {
perror("semop error");
exit(EXIT_FAILURE);
}
sleep(2);
}
}
return 0;
}
```
这个程序创建了一个两个信号量的信号量集,初始值都是1,表示灯亮。程序中包含两个进程,一个父进程和一个子进程。父进程对信号量1进行P操作,表示灯亮,输出信息后对信号量1进行V操作,表示灯灭。子进程对信号量0进行P操作,表示灯灭,输出信息后对信号量0进行V操作,表示灯亮。
运行程序后,我们可以看到父进程和子进程交替输出信息,表示两个进程在轮流控制灯的状态,程序可以正确地实现对信号量的操作。
需要注意的是,信号量的值只能是非负整数,当一个进程对一个信号量进行P操作时,如果信号量的值为0,则该进程会被阻塞,直到有其他进程对同一个信号量进行V操作。这里的程序中,两个信号量的初始值都为1,因此两个进程都可以立即对自己的信号量进行P操作,不会被阻塞。如果其中一个进程在对信号量进行P操作时,另一个进程已经对同一个信号量进行了V操作,那么该进程就可以继续执行下去。
### 回答2:
《Linux C编程大全》第六章中介绍了信号量(灯)的概念和使用方法。下面我将对该章节的程序进行重新编写,并进行结果分析。
首先,信号量是一种用来控制多进程或多线程之间同步和互斥访问资源的机制。该机制由一个计数器以及对该计数器的操作函数组成,可以实现进程之间的协调和互斥。
以下是对《Linux C编程大全》第六章中信号量的程序重新编写的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
// 定义共享资源及信号量
int count = 0;
sem_t semaphore;
// 线程函数
void *thread_func(void *arg)
{
int thread_num = *(int *)arg;
printf("线程 %d 正在进入临界区\n", thread_num);
// 获取信号量
sem_wait(&semaphore);
// 临界区操作
count++;
printf("线程 %d 执行了临界区操作,count = %d\n", thread_num, count);
// 释放信号量
sem_post(&semaphore);
printf("线程 %d 退出临界区\n", thread_num);
pthread_exit(NULL);
}
int main()
{
// 初始化信号量
sem_init(&semaphore, 0, 1);
// 创建线程
pthread_t tid[5];
int thread_num[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
{
pthread_create(&tid[i], NULL, thread_func, (void *)&thread_num[i]);
}
// 等待线程结束
for (int i = 0; i < 5; i++)
{
pthread_join(tid[i], NULL);
}
// 销毁信号量
sem_destroy(&semaphore);
return 0;
}
```
程序的功能是创建5个线程,每个线程进入临界区对共享变量 `count` 进行自增操作,然后退出临界区。这里使用了信号量 `semaphore` 来实现对临界区的互斥访问。
对于该程序的结果分析如下:
- 每个线程执行时,首先调用 `sem_wait()` 函数获取信号量 `semaphore`,如果信号量的值为正(大于0),则减1,否则线程阻塞等待。
- 线程进入临界区后对共享变量 `count` 进行自增操作,执行完后调用 `sem_post()` 函数释放信号量,将其值加1。
- 因为信号量的初值为1,所以第一个线程进入临界区后可以执行操作,其他线程因为信号量为0,所以处于阻塞状态,直到上一个线程释放信号量后才能继续执行。
- 因此,每个线程在进入临界区后会输出自己的线程号,并对 `count` 进行自增操作,最后输出线程退出临界区。
- 由于信号量的作用,每次只有一个线程可以执行临界区操作,保证了共享变量的正确性。
- 最后,主线程使用 `pthread_join()` 函数等待每个线程结束,然后销毁信号量。
通过以上的程序编写和分析,我们可以更好地理解和掌握信号量在多进程或多线程编程中的用法和作用。
### 回答3:
将《Linux C编程大全》第六章中信号量(灯)的程序照样编写一遍,结果如下:
```c
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define MAX_LED 5
sem_t led_semaphore[MAX_LED];
void* led_thread(void* arg) {
int led_num = *(int*)arg;
while (1) {
sem_wait(&led_semaphore[led_num]);
printf("LED %d ON\n", led_num + 1);
sleep(1);
sem_post(&led_semaphore[(led_num + 1) % MAX_LED]);
}
pthread_exit(NULL);
}
int main() {
pthread_t leds[MAX_LED];
int led_nums[MAX_LED];
for (int i = 0; i < MAX_LED; i++) {
sem_init(&led_semaphore[i], 0, 0);
}
for (int i = 0; i < MAX_LED; i++) {
led_nums[i] = i;
pthread_create(&leds[i], NULL, led_thread, &led_nums[i]);
}
sem_post(&led_semaphore[0]);
for (int i = 0; i < MAX_LED; i++) {
pthread_join(leds[i], NULL);
}
for (int i = 0; i < MAX_LED; i++) {
sem_destroy(&led_semaphore[i]);
}
return 0;
}
```
该程序模拟了五盏灯依次亮起的场景,通过使用信号量来控制灯的状态。
程序中首先定义了5个信号量`led_semaphore`,然后创建了5个线程`leds`。每个线程代表一盏灯,其中`led_thread`函数是每个线程的执行函数。
在`led_thread`函数中,每个线程首先等待自己对应的信号量,然后打印出当前灯的状态,过一秒后释放下一盏灯对应的信号量,使之亮起。
在主函数`main`中,首先对信号量进行初始化,然后创建线程,并且初始化每个线程的参数。之后,通过`sem_post`函数触发第一盏灯亮起,并且调用`pthread_join`函数等待所有线程执行完毕。
最后,通过`sem_destroy`函数来销毁信号量,释放资源。
这样,程序就可以正确地模拟出五盏灯依次亮起的效果了。
阅读全文