使用 5 个信号量和进程打印数字 1 到 100

Posted

技术标签:

【中文标题】使用 5 个信号量和进程打印数字 1 到 100【英文标题】:Print the numbers 1 to 100 using 5 semaphores and processes 【发布时间】:2016-03-31 03:09:06 【问题描述】:

我有一个任务是用 c 语言编写一个程序,它将向 shell 打印数字 1 - 100。我必须使用 5 个进程。第一个将打印 1, 6, 11, 16... 第二个 2, 7, 12, 17... 以此类推。 我需要创建 5 个信号量来同步这些进程。 五个信号量需要初始化为0、1、2、3、4。

这是否意味着我需要使用semctl

另外,据说打印 1 的进程必须用 4 初始化,打印 2 的进程 - 用 3 初始化,以此类推。

如何执行此操作?

最后,据说在打印一个数字之前,我需要执行等待 4 次以将信号量值减 4,打印完数字后我需要使用信号将其他信号量值增加 1。

我尝试了很多方法,但都无法解决。我不明白这些进程之间的时间安排——如何让每个进程使用某个信号量?以及如何稍后“返回”该进程,而不在我已经拥有的子进程中创建子进程?

这是我能做到的最多:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

void increaseallbutI(int i);
void cleanup();
int semid;
struct sembuf sops[1];

union semun

    int val;
    struct semid_ds * buff;
    unsigned short *array;
    struct seminfo *_buf;
;
union semun semarg;

void main()

    int i, j, k, status, num = 1;
    pid_t pid[5];

    semid=semget(IPC_PRIVATE, 5, 0600);

    for(i = 1; i < 17; i++)
    
        signal(i, &cleanup);
    

    for(i = 0; i < 5; i++)
    
        semarg.val = 4 - i;
        semctl(semid, i, SETVAL, semarg);
    

    sops->sem_num = 0;
    sops->sem_flg = 0;

    for(i = 0; i < 5; i++)
    
        if(fork()==0)
        
            for(j = i + 1; j < 101; j += 5)
            
                wait(&status);
                wait(&status);
                wait(&status);
                wait(&status);
                printf("%d\n", j);
                fflush(stdout);

                signal(i, &increaseallbutI);
            
        
    


void cleanup()

    semctl ( semid , 0 , IPC_RMID , semarg );
    exit(1);


void increaseallbutI(int i)

    int k;
    for(k = 0; k < 5; k++)
    
        if(k != i)
        
            sops->sem_op = 1;
            sops->sem_num = k;
            semop ( semid , sops , 1 );
        
    
    exit(1);

【问题讨论】:

您的程序将无法按原样运行,因为您正在使用 wait () 函数,该函数的行为是停止父进程,直到子进程返回。这意味着每个进程(父进程和子进程)都将等待永远不会到达的退出。您真正想要使用的是 sem_wait 函数,它将信号量计数减少 1,因此您需要其中的 4 个。同样,您需要某种 sem_signal 来增加信号量的值。他们是否告诉您实现自己的信号量,还是允许您使用库? 首先,非常感谢您的回答。其次,我认为我可以使用图书馆。 所以,我可以打电话给sem_wait,而不是那些waits?我应该通过什么作为论点?我需要创建一个sem_t sem 并调用sem_init(&amp;sem, 0, 0)吗? 您必须使用 sem_wait。如果您使用的是 posix 信号量,那么您应该检查文档中的正确语法,然后您应该初始化 5 个不同的信号量并正确初始化它们(这意味着使用 sem_init 和正确的信号量值,例如 sem 1 为 4 等等) . 【参考方案1】:

你的程序结构基本正确。

所以,我可以打电话给那些waits sem_wait?我应该通过什么作为论点?我需要吗 创建一个sem_t sem 并调用sem_init(&amp;sem, 0, 0)?

不,您和 ThCP 混淆了 System V 和 POSIX 信号量。由于您使用的是 System V 信号量(确实更适合您的任务),因此用于等待的函数是 semop

打印数字后我需要使用信号来增加另一个 信号量值减 1。

signal,当然不是函数signal的意思,而是你在函数increaseallbutI()中正确执行的信号量值的增加被称为signaling .

因此,主循环和程序的结尾可以变成:

    …
    for (i = 0; i < 5; i++)
    
        if (fork() == 0)
        
            struct sembuf sop =  i, -4, ;
            for (j = i + 1; j < 101; j += 5)
            
                semop(semid, &sop, 1);
                printf("%d\n", j);
                increaseallbutI(i);
            
            exit(0);    // child is done
        
    
    do ; while (wait(&status) > 0); // wait till all children are finished
    cleanup();

不要忘记删除函数 increaseallbutI() 中的 exit(1) 调用!

【讨论】:

以上是关于使用 5 个信号量和进程打印数字 1 到 100的主要内容,如果未能解决你的问题,请参考以下文章

使用互斥锁和条件变量而不是信号量在 c++14 中打印从 1 到 10 的数字?

C/C++ - sem_t 类型的单个信号量按顺序打印数字

进程数据隔离,守护进程,锁,信号量和事件

6.5.22微信怎么改微信号

题:统计数字出现次数。 随机生成100个数字,数字范围从1到10,统计每个数字出现的次数并打印到控制台。

python之-- random模块