8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何打开套接字 /proc/pid/fd/3 文件?

Luca Basso Ricci 1月前

10 0

进程的文件描述符可以在 /proc/pid/fd 目录中看到,其中一些可以打开并读取或写入。例如,如果我将某些内容通过管道传输到 stdin 上的进程,它将显示为 /proc/p...

进程的文件描述符可以在 /proc/pid/fd 目录中看到,其中一些可以打开并读取或写入。例如,如果我通过管道将某些内容传输到 stdin 上的进程,它将显示为 /proc/pid/fd/0:\'0 -> 'pipe:[19918]'|\' (ls -lF);然后我可以从另一个进程读取它,数据有时会传输到一个进程,而另一些则传输到另一个进程。

但是,如果文件描述符是套接字,则此方法不起作用。它显示为 /proc/pid/fd/3:\'3 -> 'socket:[8577]'=\',但打开它会导致出现“无此设备或地址”错误。

对于第一种情况,fd 似乎变成了命名管道,但在第二种情况下,它似乎没有变成命名套接字。现在,虽然有命名套接字,但它们是由 bind 创建的,并且必须连接到。上面的套接字将是 accept 或 socket/connect 的结果,目前还不清楚如何连接到它。

因此 open 不起作用,connect 也不起作用,因为 fd 没有被监听。有什么办法吗?在我的示例中,两种 fd 类型都在 ls 列表中显示一个数字 - 管道为 19918,套接字为 8577,表示有一个特定的内核端点可以附加到(?),但我不知道可以使用哪个 API 来附加到它。有吗?

帖子版权声明 1、本帖标题:如何打开套接字 /proc/pid/fd/3 文件?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Luca Basso Ricci在本站《linux》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 在 Linux 中,文本表示中的数字 socket:[#] 是套接字的 inode 编号,请参阅 proc_pid_fd(5) 。 inode 编号用于标识,但不用于寻址(与文件系统路径一样),因此您不能使用 open() 它们,等等。因此,inode 编号不是(如您所说)“内部端点”,而只是标识符(并且甚至不一定随着时间的推移而唯一,因为它们可以重复使用)。

    据我所知,你可以复制链接到的 fd,甚至可以跨进程复制。你可以在我的 Go fd 泄漏检查器中的 NewSocketFd .

    请记住,两个 fds(另一个进程中的 fd 以及您进程中的重复 fd)都引用同一个套接字、文件等,因此请注意不要更改 fd 引用的资源的状态。

    使用重复的 fd,您可以查询套接字配置;另请注意, fdinfo 包含带有 fd 详细信息的伪文本文件 fd 的同级目录 proc_pid_fdinfo(5) .

  • TheDiveO 的回答给了我一个线索。他的 golang NewSocketFd 使用 Linux 系统调用 pidfd_getfd,自内核 5.4 开始可用。它可以复制和读取由 pidfd_open 创建的 fd 打开的进程的 fd。pidfd_getfd 操作需要 PTRACE_MODE_ATTACH_REALCREDS 权限,这意味着除非您以 root 身份运行,否则这仅适用于获取子进程的 fd,而不仅仅是任何随机进程。以下是写入另一个进程套接字的示例代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    static int pidfd_open (pid_t pid, unsigned flags)
        { return syscall (SYS_pidfd_open, pid, flags); }
    static int pidfd_getfd (pid_t pid, unsigned targetfd, unsigned flags)
        { return syscall (SYS_pidfd_getfd, pid, targetfd, flags); }
    
    int main (int argc, const char* const* argv)
    {
        if (argc != 3) {
            printf ("Usage: %s <pid> <fd>\n", argv[0]);
            return EXIT_SUCCESS;
        }
        int pidfd = pidfd_open (atoi(argv[1]), 0);
        if (pidfd < 0) {
            perror ("pidfd_open");
            return EXIT_FAILURE;
        }
        int tfd = pidfd_getfd (pidfd, atoi(argv[2]), 0);
        if (tfd < 0)
            perror ("pidfd_getfd");
        else {
            static const char c_test_data[] = "hello world";
            if (sizeof(c_test_data) != write (tfd, c_test_data, sizeof(c_test_data)))
                perror ("write");
            close (tfd);
        }
        close (pidfd);
        return EXIT_SUCCESS;
    }
    
返回
作者最近主题: