使用共享内存将addrinfo结构从子级传递给父级

时间:2011-08-22 09:11:24

标签: c

我想使用共享内存将getaddrinfo结构(* res)的输出传递给父(来自子进程)进程,如下所示

pid = fork();
if (pid == 0)
{
    .....
    iStatus = getaddrinfo(argv[1], NULL, &hints, &servinfoC);
    ...
    shmid = shmget(GETADDR_SHM_KEY, SHMSZ, IPC_CREAT | 0666);
    ....
    shmC = shmat(shmid, (void*)NULL, 0));
    memcpy(shmC, servinfoC, sizeof(struct addrinfo));
    freeaddrinfo (servinfoC);
}
else
{
    struct addrinfo *servinfoP;
    while ((pid = waitpid (pid, &status, WUNTRACED | WCONTINUED)) > 0)
    shmid = shmget(GETADDR_SHM_KEY, SHMSZ, 0666 | IPC_CREAT);
    shmP = shmat(shmid, (void*)NULL, 0));

    /*HELP Copy shmP to servinfoP struct*/

}

我尝试了memcpy但由于addrinfo需要内存分配而没有帮助。

提前感谢您的时间和帮助

此致 的Manoj

3 个答案:

答案 0 :(得分:5)

这不起作用。 addrinfo结构包含指向其他内存区域的指针,最重要的是结果的链接列表。如果要通过共享内存传递它,则需要将其展平。

例如:

struct addrinfo_flat
{
    int ai_family;
    int ai_socktype;
    int ai_protocol;
    struct sockaddr_storage ai_addr;
    socklen_t ai_addrlen;
};

struct addrinfo_flags *addrs = (struct addrinfo_flat*)shmC;
addrs->ai_family = ai->ai_family;
addrs->ai_socktype = ai->ai_socktype;
addrs->ai_protocol = ai->ai_protocol;
memcpy(&addrs->ai_addr, ai->ai_addr, ai->ai_addrlen);
addrs->ai_addrlen = ai->ai_addrlen;

(多项结果留作练习)

答案 1 :(得分:1)

尝试将父代码更改为:

struct addrinfo servinfoP;
while ((pid = waitpid (pid, &status, WUNTRACED | WCONTINUED)) > 0)
shmid = shmget(GETADDR_SHM_KEY, SHMSZ, 0666 | IPC_CREAT);
shmP = shmat(shmid, (void*)NULL, 0));
memcpy(&servinfoP, shmP, sizeof(struct addrinfo));

现在您不必担心servinfoP的空间 - 当然如果您希望在当前环境之外提供此空间,那么您必须malloc

struct addrinfo* servinfoP = (struct addrinfo*) calloc(sizeof(struct addrinfo));

注意:这都不是c ++ ..

顺便说一句。如果你可以保证共享内存段在你需要addrinfo的时间内可用,你可以简单地转换指针,例如

struct addrinfo* servinfoP = (struct addrinfo*) shmP;

同样,在这里你不需要单独分配......

答案 2 :(得分:1)

听起来我正在尝试使用fork /进程实现异步DNS查找,这实际上是 坏主意。如果您不想要异步DNS库,只需使用线程而不是fork。然后生成的struct addrinfo已经在程序的地址空间中,并且可以被调用者使用(并释放)。

新线程应该调用getaddrinfo并在调用者完成时通知他;用于通知调用者的方法应取决于程序的事件处理方式。假设它是单线程的,你可能正在使用select / poll(或者像libevent这样的抽象),所以线程可能有意义使用你可以使用的管道{ {1}} on表示查找完成的时间。

P.S。除了需要它的传统接口(如X11)之外,切勿使用select等。有更清洁,更现代的方式来共享内存,例如shmgetmmap(对于您只能与MAP_SHARED|MAP_ANONYMOUS ed孩子共享的匿名共享内存)或fork (POSIX命名为共享内存)甚至普通文件的shm_open ......