据我所知,所有命令行 shell 都不是多线程的。特别是,即使那些支持“作业控制”(Control-Z bg
、、、fg
等)的 shell 也通过设施(即fork
、exec
信号、管道和 PTY)来实现的线程。
Emacs 也不是多线程的,尽管它能够“同时做很多事情”。 (同样,它大量分叉和执行外部程序,并使用信号、管道和 PTY 与这些外部程序进行通信。)
我的问题是,X11 协议 (X.org) 的主要实现是否在服务器或任何客户端库中使用 Unix 线程?
如果是这样,它(或其祖先,XFree86,或 XFree86 的祖先)大约什么时候开始这样做?
答案1
$ ps -eLf
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 19:25 ? 00:00:00 init [4]
...
root 1699 1 1699 0 1 19:25 ? 00:00:00 /usr/bin/kdm
root 1701 1699 1701 8 2 19:25 tty10 00:13:10 /usr/bin/X :1 vt10 ...
root 1701 1699 1703 0 2 19:25 tty10 00:00:00 /usr/bin/X :1 vt10 ...
root 1706 1699 1706 0 1 19:25 ? 00:00:00 -:1
root 1707 1699 1707 0 2 19:25 tty9 00:00:02 /usr/bin/X :0 vt9 ...
root 1707 1699 1710 0 2 19:25 tty9 00:00:00 /usr/bin/X :0 vt9 ...
root 1713 1699 1713 0 1 19:25 ? 00:00:00 -:0
....
我认为回答了你的问题。
尽管如此,问题似乎是将几个东西混合在一起 - 多线程并不是不使用fork()
/ exec()
。线程共享相同的地址空间,如果您想运行不同的进程,您当然不希望它访问相同的地址空间。如果您决定不使用外部程序(尤其是在您提到的 shell 中),则必须再次编写所有功能的代码。
多线程并不能解决所有问题。实际上,它主要只能解决可并行化问题 - 检查维基页面一个很好的简短概述。使程序成为多线程并不会使其变得更好,在大多数情况下,由于同步代码中的错误(如果存在),它会使情况变得更糟。
答案2
在 ES Raymond 的书中,作者引用了 。
X 服务器每秒能够执行数百万次操作,但它不是线程化的;它使用轮询/选择循环。进行多线程实现的各种努力都没有取得好的结果。对于像图形服务器这样对性能敏感的东西来说,锁定和解锁的成本太高了。 ——吉姆·盖蒂斯
答案3
答案4
这不是对问题的直接回答,但我觉得它澄清了事情,而且评论太长了。
我认为,你不应该将 UNIX 线程与进程进行比较(fork()
)。这个问题似乎表明线程在某种程度上取代了进程,但事实并非如此。它们都有各自的优点和缺点,最终由程序员决定使用哪一种(如果有的话)。重新实现也是如此。
如果使用线程有其优点,那么基本工具就会被重新实现,或者至少会有一个针对它的分叉。
就我个人而言,我认为对于像 shell 这样的任务,多重处理是更好的选择,因为您的 shell 得到了很多保护:它启动的进程可能会变得疯狂,但不会导致 shell 崩溃。
另一方面,例如,信号被传递到所有线程,因此线程 shell 必须能够承受针对实用程序线程/由实用程序线程创建的信号,同时传递这些信号,因为实用程序线程可能会需要他们...
总而言之:多处理允许更好地分离 shell 和它启动的进程,并为 shell 启动的进程提供更多自由以获取信号,可能还有一堆我想不到的其他东西。