程序卡在while循环中

时间:2019-10-08 16:59:29

标签: c while-loop semaphore

我试图在while循环中使用信号量,并且我的程序在无限循环中运行。基本上,我派生孩子并使用execv启动新的用户进程。进程使用共享内存中的信号量进行通信。

struct shared
{
int count;
sem_t sem;
} *shmem;
void forking()
{
key_t shmkey = ftok("makefile",777);
        if (shmkey == -1) {
            perror("Ftok failed");
            exit(-1);
        }

        // Get our shm id
        shmid = shmget(shmkey, sizeof(shared), 0666 | IPC_CREAT);
        if (shmid == -1) {
            perror("Failed to allocate shared memory region");
            exit(-1);
        }

        // Attach to our shared memory
        shmem = (shared*)shmat(shmid, (void *)0, 0);
        if (shmem == (void *)-1) {
            perror("Failed to attach to shared memory region");
            exit(-1);
        }

    sem_init(&(shmem->sem),1,1);
    pid_t PID;
    int i;
    for(i=0;i<4;i++)
    {
    PID=fork();
    if(PID==0)
    {
        static char *args[]={"./child",NULL};
        int status;
        if(( status= (execv(args[0], args)))==-1)
        perror("failed to execv");
        exit(EXIT_FAILURE);
    }
    if(PID>0)
    {
        while(1)
        {
            sem_wait(&(shmem->sem));
            {
                shmem->count=shmem->count+1;
            }
            sem_post(&(shmem->sem));
        }
    }
    if(PID<0)
    perror("error in fork");
    }
}
main()
{
    forking();
}

在child.c

struct shared
{
int count;
sem_t sem;
} shmem;
void main()
{
    bool alive=true;
    do
    {
    sem_wait(&(shmem->sem));
    if(shmem->count==5)
    {
        shmem->count=0; 
        alive=false;
    }
    sem_post(&(shmem->sem));
    }while(alive);
}

child.c无休止地循环,而不允许父级将i递增到5。即使我在第一个文件中的while循环中注释掉并且只是让它递增而没有循环,也会发生这种情况。

1 个答案:

答案 0 :(得分:1)

您使用的fork错误,并且绝对不使用共享内存。

这里有几点

  1. 通过调用fork,您将复制在不同内存空间中运行的parent。 http://man7.org/linux/man-pages/man2/fork.2.html
  2. 通过使用execve,您实际上删除了旧的内存,并用新的内存替换了,这些内存始终未链接到您的父进程。 http://man7.org/linux/man-pages/man2/execve.2.html

要使代码正常工作,您应该使用pthread_*,因为它将存在于相同的内存空间中,并使全局变量具有可变性,因为gcc会尝试优化并具有这样做会产生奇怪的行为。

好吧,我似乎已经错失了很多要点,但我的假设并没有完全错。

所以您的child.c缺少很多代码

  1. 它不包含您在父级中进行的所有初始化,这是必需的,因为如果使用execve,则实际上会丢失以前在父级进程中映射的所有内存映射。
  2. 您的父母会无限循环,因此shmem->count永远不会真正等于5,您将不得不在某些时候中断或更改子代码中的条件。

这就是你的孩子的样子。

#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

typedef struct
{
    int count;
    sem_t sem;
} shared;

shared *shmem;
int shmid;
key_t shmkey;

int main()
{
    int alive=1;

    shmkey = ftok("makefile",777);
    if (shmkey == -1) {
        perror("Ftok failed");
        exit(-1);
    }

    // Get our shm id
    shmid = shmget(shmkey, sizeof *shmem, 0);
    if (shmid == -1) {
        perror("Failed to allocate shared memory region");
        exit(-1);
    }

    // Attach to our shared memory
    shmem = (shared*)shmat(shmid, (void *)0, 0);
    if (shmem == (shared *)-1) {
        perror("Failed to attach to shared memory region");
        exit(-1);
    }

    do
    {
        sem_wait(&(shmem->sem));
        printf("%d\n", shmem->count);
        if(shmem->count > 5)
        {
            shmem->count=0; 
            alive=0;
        }
        sem_post(&(shmem->sem));
    }while(alive);

    printf("I have finished %u\n", getpid());
    exit(0);
}