首页 文章

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

提问于
浏览
3

我有一个用c语言编写程序的任务,它将打印到shell的数字1 - 100.我必须使用5个进程 . 第一个将打印1,6,11,16 ......第二个,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);
}

1 回答

  • 0

    你的程序结构基本上是正确的 .

    那么,而不是那些等待,我可以调用sem_wait?我应该作为一个论点传递什么?我是否需要创建sem_t sem并调用sem_init(&sem,0,0)?

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

    打印数字后,我需要使用信号将其他信号量值增加1 .

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

    因此,主循环和程序的结束可能变为:

    …
        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) 调用!

相关问题