【问题标题】:Pass data from parent process to its child process — IPC, UNIX将数据从父进程传递到其子进程——IPC、UNIX
【发布时间】:2016-03-31 04:29:51
【问题描述】:

我正在尝试用 C 语言为 Unix 创建一个程序。给定一个数组,我应该通过共享内存并使用信号量将数组的每个项目从父进程传递给它的子进程。 这就是我所拥有的。

const key_t sem_key = (key_t)0x12345611;
const key_t shm_key = (key_t)0x12339611;

int sem_wait(int semafor_id)
{
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = -1;
    sb.sem_flg = SEM_UNDO;

    return semop(semafor_id, &sb, 1);
}

int sem_signal(int semafor_id)
{
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = 1;
    sb.sem_flg = SEM_UNDO;

    return semop(semafor_id, &sb, 1);
}

int main(int argc, char *argv[])
{
    int status;
    char str[3];
    str[0] = 'z';
    str[1] = 'x';
    str[2] = 'y';

    // Create shared memory
    int memory_id = shmget(shm_key, 1, 0600 | IPC_CREAT | IPC_EXCL);
    if (memory_id < 0)
    {
        printf("Shared memory creating failed\n");
        return 1;
    }

    // Create semafor
    int semafor_id = semget(sem_key, 10, 0600 | IPC_CREAT | IPC_EXCL);
    if (semafor_id < 0)
    {
        printf("SEMAFOR creating failed\n");
        return 1;
    }
    semctl(semafor_id, 0, SETVAL, 1); // init semafor

    pid_t pid = fork();
    if (pid < 0)
        printf("FORK FAILED\n");

    else if (pid > 0)
    {
        printf("PARENT\n");
        void *address = shmat(memory_id, NULL, 0);
        if (address == NULL)
        {
            printf("Failed to attach memory\n");
            return 1;
        }
        if (sem_wait(semafor_id) < 0) // sem_wait() decrements (locks) the semaphore pointed to by sem.
        {
            printf("Failed wait parent\n");
            return 1;
        }

        for (int i = 0; i < 3; i++)
        {
            void *address = shmat(memory_id, NULL, 0);
            if (address == NULL)
            {
                printf("Failed to attach memory\n");
                return 1;
            }
            printf("writer started.\n");
            char *data = (char *) address;
            *data = str[i];
            printf("writer ended.\n");
        }

        if (shmdt(address) != 0)
            printf("Failed to detach shared memory\n");

        if (sem_signal(semafor_id) < 0)
            printf("Failed signal parent\n");
        else
            printf("Parent leave generating number\n");


        // wait for child
        wait(&status);
        printf("Destroy semafor\n");
        semctl(semafor_id, 0, IPC_RMID, 0);
        printf("Destroy shared memory\n");
        shmctl(memory_id, IPC_RMID, 0);

        return 0;
    } // close parent case
    else
    {
        printf("CHILD\n");
        if (sem_wait(semafor_id) < 0)
            printf("FAILED wait child\n");
        else
        {
            void *address = shmat(memory_id, NULL, 0);
            if (address == NULL)
            {
                printf("Failed to atach memory in child\n");
                return 1;
            }
            char *data = (char *) address;
            printf("Child read data %c\n", *data);

            if (shmdt(address) != 0)
                printf("Failed to detach shared memory in child\n");
        }
    }

    if (sem_signal(semafor_id) < 0)
        printf("Failed signal child\n");
    else
        printf("Leave data reading\n");

    return 0;
}

当前的输出是这样的:

writer started
writer ended
writer started
writer ended
writer started
writer ended
child read data y
destroy semafor
destroy shared memory 

您可以看到父级在共享内存中写入 3 次,然后子级访问共享内存并打印共享内存的数据。 我想要的输出是这样的:

writer started
writer ended
child read data z
writer started
writer ended
child read data x 
writer started
writer ended
child read data y
destroy semafor
destroy shared memory  

【问题讨论】:

  • 屏幕截图是不必要的,你可以复制/粘贴你想要的输出。只需将其标记为“当前输出”。祝你好运。
  • 这段代码存在多个问题。这是家庭任务吗?你到底有什么不清楚的地方?

标签: c unix ipc semaphore shared-memory


【解决方案1】:

问题在于逻辑。去掉样板代码后,逻辑如下:

Get shared memory
Get semaphore with value 1
fork
in parent:
    wait semaphore (problem #1, #2) <-- supposed to decrement it to 0

    for(i=0;i<3;++i)
    {
        write next char <<-- no synchronization here :-(
    }

    signal semaphore 

    wait for child
    STOP

in child:
    wait semaphore (problem #1)
    read next char
    signal semaphore
    (problem #3)
    STOP

英文:

the writer acquires write lock
writes 3 values into the same location
then signals the reader to read data.
At this moment writer moves on to wait for child PID to die.

The reader reads the last value once
signals the semaphore
then exits.

At this moment writer sees reader died
cleans up
...and exits

问题 #1:父进程和子进程同时运行。 他们中的任何一个都可以先在sem_wait 取得成功。如果孩子先这样做,它会 从共享内存和父级打印出乱码的初始未初始化值 将永远锁定等待信号量。 尝试在等待信号量之前将虚构(或不)睡眠(1)添加到父级中。 这将模拟处理器上下文切换。

问题 #2:您只等待/发出信号一次。例如。你写下所有的值,然后才发出信号。 这就是为什么只打印最后一个值的原因。

问题#3:孩子没有任何循环。他应该如何读取 3 个值?!

逻辑应该是:

Writer
    Do 3 times:
        acquire write semaphore
        write next value
        signal reader semaphore
    wait child to die
    clean up
    exit

reader:
    Do 3 times:
       acquire reader semaphore
       read next value
       signal writer semaphore
    exit

【讨论】:

  • 我需要多少信号量? 1 或 2(读取器信号量和写入器信号量)?
  • 是的,因为问题 #1,您需要一个写信号量和一个读信号量。
猜你喜欢
  • 2018-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-03
相关资源
最近更新 更多