简体   繁体   English

fork exec和mmap问题

[英]fork exec and mmap issues

For the application I'm developing (under Linux, but I'm trying to maintain portability) I need to switch to shared memory for sharing data across different processes (and threads inside processes). 对于我正在开发的应用程序(在Linux下,但我正在尝试维护可移植性)我需要切换到共享内存,以便跨不同进程(以及进程内的线程)共享数据。 There is a father process generating different children 有一个父亲过程产生不同的孩子

I need for example to get every process able to increment a shared counter using a named semaphore. 例如,我需要使每个进程能够使用命名信号量递增共享计数器。

In this case everything is ok: 在这种情况下,一切都很好:

#include <sys/mman.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <fcntl.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;

#define SEM_NAME "/mysem"
#define SM_NAME "tmp_sm.txt"

int main(){
    int fd, nloop, counter_reset;
    int *smo;
    sem_t *mutex;

    nloop = 100;
    counter_reset = 1000;

    if (fork() == 0) {
        /* child */
        /* create, initialize, and unlink semaphore */
        mutex = sem_open(SEM_NAME, O_CREAT, 0777, 1);
        //sem_unlink(SEM_NAME);
        /* open file, initialize to 0, map into memory */
        fd = open(SM_NAME, O_RDWR | O_CREAT);
        smo = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        close(fd);
        /* INCREMENT */
        for (int i = 0; i < nloop; i++) {
            sem_wait(mutex);
            cout << "child: " << (*smo)++ << endl;
            if(*smo>=counter_reset){
                (*smo)=0;
            }
            sem_post(mutex);
        }
        exit(0);
    }
    /* parent */
    /* create, initialize, and unlink semaphore */
    mutex = sem_open(SEM_NAME, O_CREAT, 0777, 1);
    sem_unlink(SEM_NAME);
    /* open file, initialize to 0, map into memory */
    fd = open(SM_NAME, O_RDWR | O_CREAT);
    smo = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    close(fd);
    /* INCREMENT */
    for (int i = 0; i < nloop; i++) {
        sem_wait(mutex);
        cout << "parent: " << (*smo)++ << endl;
        if(*smo>=counter_reset){
            (*smo)=0;
        }
        sem_post(mutex);
    }
    exit(0);
}

So far so good: both semaphore and shared counter are ok (same address in memory) and increment and reset work fine. 到目前为止一切顺利:信号量和共享计数器都可以(内存中的地址相同),增量和重置工作正常。

The program fails simply by moving child source code into a new source file invoked by exec. 该程序只是通过将子源代码移动到exec调用的新源文件中而失败。 Shared memory and named semaphore addresses are different therefore increment fails. 共享内存和命名信号量地址不同,因此增量失败。

Any suggestion? 有什么建议吗? I used named semaphores and named shared memory (using a file) to try to get the same pointer values. 我使用命名信号量并命名共享内存(使用文件)来尝试获取相同的指针值。


UPDATE: 更新:

as requested by Joachim Pileborg, this is the "server side" improvements respect above original code: 按照Joachim Pileborg的要求,这是对原始代码的“服务器端”改进方面:

...
if (fork() == 0) {
    /* child */
    /*spawn child by execl*/
    char cmd[] = "/path_to_bin/client";
    execl(cmd, cmd, (char *)0);
    cerr << "error while istantiating new process" << endl;
    exit(EXIT_FAILURE);
}
...

And this is the "client" source code: 这是“客户端”源代码:

#include <sys/mman.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <fcntl.h>
#include <iostream>
#include <stdlib.h>
using namespace std;

#define SEM_NAME "/mysem"
#define SM_NAME "tmp_ssm.txt"

int main(){
    int nloop, counter_reset;
    int *smo;
    sem_t *mutex;
    /* create, initialize, and unlink semaphore */
    mutex = sem_open(SEM_NAME, O_CREAT, 0777, 1);
    //sem_unlink(SEM_NAME);
    /* open file, initialize to 0, map into memory */
    int fd = open(SM_NAME, O_RDWR | O_CREAT);
    smo = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    close(fd);
    nloop=100;
    counter_reset=1000;
    /* INCREMENT */
    for (int i = 0; i < nloop; i++) {
        sem_wait(mutex);
        cout << "child: " << (*smo)++ << endl;
        if(*smo>=counter_reset){
            (*smo)=0;
        }
        sem_post(mutex);
    }
    exit(0);
}

executing this code cause the process to block (deadlock) and waiting for an infinite time. 执行此代码会导致进程阻塞(死锁)并等待无限时间。 looking at addresses they are tipically found to be: 看着他们被发现的地址:

father semaphore: 0x7f2fe1813000
child semahpore: 0x7f0c4c793000
father shared memory: 0x7f2fe1811000
child shared memory: 0x7ffd175cb000

removing 'sem_post' and 'sem_wait' everything is fine but I need mutual exlusion while incrementing... 删除'sem_post'和'sem_wait'一切都很好,但我需要在增加时相互排斥......

Don't unlink the semaphore. 不要取消信号量的链接。 it actually removes the semaphore. 它实际上删除了信号量。

From the sem_unlink manual page: sem_unlink手册页:

sem_unlink() removes the named semaphore referred to by name. sem_unlink()删除name引用的命名信号量。 The semaphore name is removed immediately. 信号量名称立即被删除。 The semaphore is destroyed once all other processes that have the semaphore open close it. 一旦所有其他具有信号量打开的进程关闭它,信号量就会被破坏。

This means that once you've created the semaphore in the parent process, you immediately remove it. 这意味着一旦您在父进程中创建了信号量,就会立即将其删除。 The child process then will not be able to find the semaphore, and instead creates a new one. 然后子进程将无法找到信号量,而是创建一个新的信号量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM