5

Linux 上拥有更多线程的进程是否会比拥有一个线程的进程拥有更多的 CPU 时间?

在 Linux 中,进程和线程由 task 结构描述,调度是基于 tasks 的。我还发现了这个

创建新进程时do_fork(),按以下方式设置当前(父)和 p(子)进程的计数器字段:

current->counter >>= 1;
p->counter = current->counter;

换句话说,留给父母的滴答数被分成两半,一份给父母,一份给孩子。这样做是为了防止用户通过使用以下方法获得无限量的 CPU 时间:父进程创建一个运行相同代码的子进程,然后杀死自己;通过适当调整创建速率,子进程将始终在其父进程的量程到期之前获得一个新的量程。这个编程技巧不起作用,因为内核不奖励分叉。类似地,用户不能通过在 shell 中启动大量后台进程或在图形桌面上打开大量窗口来占用处理器的不公平份额。更一般地说,一个进程不能通过分叉多个后代来占用资源(除非它有权给自己一个实时策略)。

实际上我在内核源代码中没有找到,但也许是我的错,也许我看到了错误的内核版本。

但是以后会发生什么,每个线程会像一个单独的进程一样参与调度吗?一个有十个线程的进程会比一个有一个线程的进程获得十倍的滴答声吗?从这个意义上说,IO 呢?

4

1 回答 1

11

是的,具有更多线程的进程将获得比其竞争对手更多的 CPU 时间。一个众所周知的案例是 maven 编译,maven 使用大量 CPU 密集型线程,占用系统。

但是,当前的 linux 调度程序不仅考虑了任务,还考虑了 cpu cgroup 层次结构中的控制组。因此,CPU时间在控制组之间分配,然后在每个控制组中,CPU时间在任务之间分配。

从 2.6.38 开始,Linux 会根据会话 id 自动将任务放入不同的 cpu cgroup。这意味着例如: konsole/gnome-terminal 中的单独选项卡有自己的控制组。所以现在你的 maven 编译很好地隔离了,不再占用系统。请参阅kernelnewbieslwn.net上的描述。

在 2.6.38 击中大多数系统之前,Lennart Poettering 在此 LKML 消息中展示了如何在 shell 脚本上手动执行此操作。

实际上,我有一个运行 Eclipse 和 maven 编译的系统,从 pre-2.6.38 到 pre-2.6.38 + Lennart 的 cgroup 绑定(我在我/etc/bashrc Eclipse 启动器脚本上放置)的变化非常完美。Maven 不再占用系统(如果不是 CPU 负载监视器,你不会知道有一个 Maven 编译正在进行),Eclipse 现在只是占用自己,而不是系统的其余部分(我会满足于Eclipse)。现在我只需要将内核更新为具有更好的脏页写回功能的内核,该系统将变得轻而易举。

于 2012-10-03T19:24:29.973 回答