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

eev*_*e25 5 c linux semaphore

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

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

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

我该如何执行此操作?

最后据说在打印一个数字之前我需要执行4次wait来将信号量值减4,而在打印数字之后我需要使用signal将其他信号量值加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);
}
Run Code Online (Sandbox Code Playgroud)

Arm*_*ali 0

你的程序结构基本是正确的。

\n\n
\n

那么,wait我可以调用 \n 来代替那些 s sem_wait?我应该传递什么作为参数?我需要\n 创建sem_t sem并调用sem_init(&sem, 0, 0)吗?

\n
\n\n

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

\n\n
\n

打印数字后,我需要使用 signal 将其他\n 信号量值加 1。

\n
\n\n

通过信号,当然不是指函数signal,而是在函数中正确执行的信号量值的增加increaseallbutI()称为信号发送

\n\n

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

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

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

\n