c 解放漏れ Linux上の別のプロセスにファイル記述子を共有することはできますか?それともプロセスのローカルですか?




ファイルディスクリプタ 解放漏れ (4)

上記の例では、受信時の変数の設定は次のようになります。

msg.msg_name = NULL;
msg.msg_namelen = 0;

iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;

必須ではありません。 ヘッダーを含むメッセージ構造の全体的な考え方は、受信サイトが読み取る内容を知る必要はなく、ヘッダー(最初のヘッダー)、どのようなメッセージであるか、そして何を期待するかによって確認できます。

ProcessAとProcessBの2つのプロセスがあるとします。 ProcessAでint fd=open(somefile)を実行すると、ファイルディスクリプタfd値をIPC経由でProcessBに渡して、同じファイルを操作できますか?


このスレッドで説明されているメソッド、または(より一般的な)方法を、関連するプロセス(親子または兄弟など)間で共有することによって作成できます。forkされたプロセスは自動的にコピーを受け取ります。

実際、フォークされたプロセスはすべてのFDを取得し、クローズしない限り使用できます(一般的には良いアイデアです)。

したがって、親が2つの子をフォークした場合、それらが両方とも閉じなかったファイル記述子を持っていれば、それは今共有されます(親がその後それを閉じても)。 これは、例えば、ある子供から別の子供へのパイプである可能性があります。 これは、シェルのリダイレクト方法です

ls -l | more

作業。


両方のプロセスが同じユーザーに属している場合は、procfsを使用するだけです。

char fd_path[64];  // actual maximal length: 37 for 64bit systems
snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", SOURCE_PID, SOURCE_FD);
int new_fd = open(fd_path, O_RDWR);

もちろん、 SOURCE_FDの値を共有するには、IPCメカニズムが必要SOURCE_FD 。 例えば、 " Linux C:シグナルを受信したときに、送信者のPIDを知ることは可能でしょうか? "


Unixドメインソケットを介してファイル記述子を別のプロセスに渡すことができます。 このようなファイル記述子を渡すコードは、 Unix Network Programming

ssize_t
write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
    struct msghdr   msg;
    struct iovec    iov[1];

#ifdef  HAVE_MSGHDR_MSG_CONTROL
    union {
      struct cmsghdr    cm;
      char              control[CMSG_SPACE(sizeof(int))];
    } control_un;
    struct cmsghdr  *cmptr;

    msg.msg_control = control_un.control;
    msg.msg_controllen = sizeof(control_un.control);

    cmptr = CMSG_FIRSTHDR(&msg);
    cmptr->cmsg_len = CMSG_LEN(sizeof(int));
    cmptr->cmsg_level = SOL_SOCKET;
    cmptr->cmsg_type = SCM_RIGHTS;
    *((int *) CMSG_DATA(cmptr)) = sendfd;
#else
    msg.msg_accrights = (caddr_t) &sendfd;
    msg.msg_accrightslen = sizeof(int);
#endif

    msg.msg_name = NULL;
    msg.msg_namelen = 0;

    iov[0].iov_base = ptr;
    iov[0].iov_len = nbytes;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    return(sendmsg(fd, &msg, 0));
}
/* end write_fd */

ファイル記述子を受け取るコードは次のとおりです

ssize_t
read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
    struct msghdr   msg;
    struct iovec    iov[1];
    ssize_t         n;
    int             newfd;

#ifdef  HAVE_MSGHDR_MSG_CONTROL
    union {
      struct cmsghdr    cm;
      char              control[CMSG_SPACE(sizeof(int))];
    } control_un;
    struct cmsghdr  *cmptr;

    msg.msg_control = control_un.control;
    msg.msg_controllen = sizeof(control_un.control);
#else
    msg.msg_accrights = (caddr_t) &newfd;
    msg.msg_accrightslen = sizeof(int);
#endif

    msg.msg_name = NULL;
    msg.msg_namelen = 0;

    iov[0].iov_base = ptr;
    iov[0].iov_len = nbytes;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    if ( (n = recvmsg(fd, &msg, 0)) <= 0)
        return(n);

#ifdef  HAVE_MSGHDR_MSG_CONTROL
    if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
        cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
        if (cmptr->cmsg_level != SOL_SOCKET)
            err_quit("control level != SOL_SOCKET");
        if (cmptr->cmsg_type != SCM_RIGHTS)
            err_quit("control type != SCM_RIGHTS");
        *recvfd = *((int *) CMSG_DATA(cmptr));
    } else
        *recvfd = -1;       /* descriptor was not passed */
#else
/* *INDENT-OFF* */
    if (msg.msg_accrightslen == sizeof(int))
        *recvfd = newfd;
    else
        *recvfd = -1;       /* descriptor was not passed */
/* *INDENT-ON* */
#endif

    return(n);
}
/* end read_fd */




linux