AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 531171
Accepted
Lassi
Lassi
Asked: 2019-07-21 06:00:10 +0800 CST2019-07-21 06:00:10 +0800 CST 2019-07-21 06:00:10 +0800 CST

为什么 fork() 应该被设计成返回一个文件描述符?

  • 772

在他关于self-pipe 技巧的网页上,Dan Bernstein 解释了一个带有和信号的竞争条件,提供了一种解决方法并得出结论:select()

当然,正确的做法是fork()返回文件描述符,而不是进程 ID。

他的意思是什么——它是关于能够select()在子进程上处理它们的状态变化而不是必须使用信号处理程序来获得这些状态变化的通知吗?

signals file-descriptors
  • 4 4 个回答
  • 3008 Views

4 个回答

  • Voted
  1. Best Answer
    ilkkachu
    2019-07-21T06:12:28+08:002019-07-21T06:12:28+08:00

    该问题在您的源代码中进行了描述,select()应该被类似的信号中断SIGCHLD,但在某些情况下它不能很好地工作。所以解决方法是将信号写入管道,然后由select(). 监视文件描述符select()是为了解决这个问题。

    解决方法实质上是将信号事件转换为文件描述符事件。如果fork()一开始只返回一个 fd,则不需要解决方法,因为该 fd 可能会直接与select().

    所以是的,你在最后一段中的描述对我来说似乎是正确的。


    fd(或某种其他类型的内核句柄)比普通进程 ID 号更好的另一个原因是 PID 可以在进程终止后重用。在某些情况下,当向进程发送信号时,这可能是一个问题,可能无法确定该进程是您认为的进程,而不是另一个重用相同 PID 的进程。(虽然我认为在向子进程发送信号时这应该不是问题,因为父进程必须在子进程上运行wait()才能释放其 PID。)

    • 13
  2. user732
    2019-07-21T06:14:01+08:002019-07-21T06:14:01+08:00

    Bernstein 没有为这个“正确的事情”评论提供太多背景信息,但我会冒险猜测:让 fork(2) 返回 PID 与 open(2)、creat(2) 等返回文件描述符不一致。Unix 系统的其余部分可以使用代表进程的文件描述符而不是 PID 来完成进程操作。存在一个系统调用signalfd(2),它允许信号和文件描述符之间更好的交互,并表明表示进程的文件描述符可以工作。

    • 8
  3. mosvy
    2019-07-21T15:35:00+08:002019-07-21T15:35:00+08:00

    这只是对“如果 Unix 的设计不同于它的设计,那就太好了”的思考。

    PID 的问题在于它们存在于一个全局命名空间中,可以在其中为另一个进程重用它们,如果fork()在父进程中返回某种可以保证始终引用子进程的句柄,那就太好了,并且它可以通过继承或 unix 套接字 / SCM_RIGHTS[1] 传递给其他进程。

    另请参阅此处的讨论,了解最近在 Linux 中“修复”该问题的努力,包括添加一个标志,clone()使其返回 pid-fd 而不是 PID。

    但即便如此,这也不会消除对自管道 hack [2] 或更好接口的需求,因为通知父进程有关子进程状态的信号并不是您希望在主循环中处理的唯一信号的程序。不幸的是,像epoll(7) + signalfd(2)Linux 或kqueue(2)BSD 这样的东西不是标准的——唯一的标准接口(但在旧系统上不支持)是低劣的pselect(2)。

    [1] 防止 PID 在系统调用返回并使用其返回值时被重新循环,waitpid()可能可以在较新的系统上通过使用waitid(.., WNOWAIT)来实现。

    [2] 我不会评论 DJ Bernstein 声称他发明了它(对不起,apophasis ;-))。

    • 8
  4. mtk
    2020-02-19T03:34:12+08:002020-02-19T03:34:12+08:00

    关键是有许多程序基于使用select(2) / poll(2) / epoll(7)监视文件描述符来操作事件循环样式模型。但是有各种事件在历史上没有使用文件描述符通知——其中包括子进程的进程状态转换(例如,终止)。需要单独处理这些其他事件(包括计时器到期、信号和同步事件,例如信号量更改),使事件循环模型的编程变得复杂。

    在过去的几年里,Linux 开发一直在解决这个问题,所以现在我们有了signalfd(2)(使信号可以从文件描述符中读取)、eventfd(2)(句柄是文件描述符的同步原语) , 和timerfd_create(2)(创建通过文件描述符通知的计时器),所有这些都会产生可以提供给select(2) / poll(2) / epoll(7)的文件描述符。

    最后,最近的 Linux 版本添加了进程句柄作为文件描述符的概念。clone3()的CLONE_PIDFD标志可用于创建一个子进程,为其返回一个文件描述符作为句柄。文件描述符同样可以提供给select(2) / poll(2) / epoll(7)并指示子进程是否终止是可读的。

    • 1

相关问题

  • 陷阱处理程序不起作用?

  • 为什么分叉进程之间共享文件描述符?

  • 以两种不同的方式处理 SIGALRM

  • 为什么已经存在 SIGSTOP 时存在 SIGTSTP?

  • 调试的信号编号是 1 到 64 中的哪个数字?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve