programing

Linux 상의 다른 프로세스와 파일 기술자를 공유할 수 있습니까?아니면 로컬 프로세스입니까?

prostudy 2022. 7. 31. 21:10
반응형

Linux 상의 다른 프로세스와 파일 기술자를 공유할 수 있습니까?아니면 로컬 프로세스입니까?

예를 들어 프로세스 A와 프로세스 B의 2가지 프로세스가 있다고 합시다.제가 공연을 하면int fd=open(somefile)프로세스 A에서 파일 기술자의 값을 전달할 수 있습니까?fdIPC를 경유하여 프로세스 B에 접속하여 동일한 파일을 조작하고 있는지 확인합니다.

UNIX 도메인 소켓을 통해 파일 기술자를 다른 프로세스에 전달할 수 있습니다.다음은 UNIX 네트워크 프로그래밍에서 가져온 이러한 파일 기술자를 전달하기 위한 코드입니다.

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 */

2020년에 Linux 버전 5.6 이상에서는 새로운 시스템콜이 Linux에 추가되어 프로세스가 pidfd에 의해 참조되는 다른 프로세스의 파일 기술자의 복제를 취득할 수 있게 되었습니다.pidfd_getfd()시스템 콜을 실행합니다.

양쪽 프로세스가 같은 유저에 속하는 경우는, 간단하게 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);

물론 IPC 메커니즘이 있어야 가치를 공유할 수 있습니다.SOURCE_FD. 를 참조해 주세요."Linux C: 신호를 수신하면 송신자의 PID를 알 수 있습니까?"

이 스레드에 기술되어 있는nos 메서드를 사용하거나 (일반적으로 부모-자녀 또는 형제자매) 관련 프로세스 간에 공유함으로써 분기된 프로세스가 자동으로 복사본을 수신할 수 있습니다.

실제로 분기된 프로세스는 모든 FD를 취득하고 FD를 닫지 않는 한 FD를 사용할 수 있습니다(일반적으로 이 방법이 좋습니다).

따라서 부모가 두 아이를 포킹하고 둘 다 닫지 않은 파일 설명자가 있는 경우, 이제 공유됩니다(부모가 나중에 닫더라도).예를 들어, 이것은 한 아이에서 다른 아이로 가는 파이프일 수 있습니다.셸 리다이렉트 방법은 다음과 같습니다.

ls -l | more

일하다.

위의 예에서는 수신 시 변수의 설정은 다음과 같습니다.

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;

는 필수가 아닙니다.헤더가 있는 메시지 구조의 전체 개념은 수신 사이트가 무엇을 읽는지 알 필요가 없으며, (첫 번째) 헤더를 체크함으로써 어떤 종류의 메시지인지, 무엇을 예상할 수 있다는 것입니다.

언급URL : https://stackoverflow.com/questions/2358684/can-i-share-a-file-descriptor-to-another-process-on-linux-or-are-they-local-to-t

반응형