Perl 线程 - 它们可以唯一命名吗?(Linux)



引用Perlvar:

在多线程脚本中,Perl 协调线程,以便任何线程都可以修改其 $0 的副本,并且更改对 ps(1( 可见(假设操作系统一起播放(。请注意,其他线程的 $0 视图不会改变,因为它们有自己的副本。

我似乎没有这种行为。相反,$0 似乎由我的所有线程共享,并且在 ps 输出中,顶级主 perl 解释器的 cmdline 正在修改为最后一个线程应用的最终值。

例如。 我的目标是不让所有线程在 COMMAND 列下命名相同:

top -b -n 1 -H -p 223860
top - 17:54:56 up 73 days,  2:15,  7 users,  load average: 0.23, 0.70, 0.92
Threads:  22 total,   0 running,  22 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 32358832 total, 26418060 free,  1090028 used,  4850744 buff/cache
KiB Swap: 16777212 total, 16149116 free,   628096 used. 30804716 avail Mem
PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
223860 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:45.75 tool_reader.
223863 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:03.88 tool_reader.
223864 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:04.67 tool_reader.
223865 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:00.00 tool_reader.
223867 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:34.62 tool_reader.
223868 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:03.85 tool_reader.
223869 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:04.41 tool_reader.
223870 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:00.00 tool_reader.
223872 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:40.14 tool_reader.

在这样的命令列下有更有用的东西,并且主线程保持不变。

       |
       |
       |
       v
top -b -n 1 -H -p 223860
top - 17:54:56 up 73 days,  2:15,  7 users,  load average: 0.23, 0.70, 0.92
Threads:  22 total,   0 running,  22 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 32358832 total, 26418060 free,  1090028 used,  4850744 buff/cache
KiB Swap: 16777212 total, 16149116 free,   628096 used. 30804716 avail Mem
PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
223860 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:45.75 tool_reader.
223863 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:03.88 syncer
223864 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:04.67 partition1
223865 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:00.00 partition2
223867 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:34.62 partition3
223868 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:03.85 input_merger1
223869 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:04.41 input_merger2
223870 app_sy+  20   0 3833640 166216   2500 S  0.0  0.5   0:00.00 input_merger3

有谁知道这是怎么做到的?我现在正在使用一个相当旧的perl,版本5.16.3,以防这是一个错误?

更新 2020-10-21:我刚刚发现了一种更好的方法来实现这一目标 - 实际的 linux 系统调用。 https://man7.org/linux/man-pages/man2/prctl.2.html

Troels Liebe Bentsen 慷慨地贡献了一个模块来巧妙地处理这个问题。 https://metacpan.org/pod/Sys::Prctl

远比摆弄 0 美元!!无缝

原始帖子内容在下面继续....

ps -T -p 126193
PID   SPID TTY          TIME CMD
126193 126193 pts/11   00:00:00 test2.pl
126193 126194 pts/11   00:00:00 __thr1      #<--- now unique
126193 126195 pts/11   00:00:00 __thr2      #<--- now unique
top -H -p 126193
PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
126193 xxxxxxx+  20   0  305948   7972   2244 S  0.0  0.0   0:00.01 test2.pl
126194 xxxxxxx+  20   0  305948   7972   2244 S  0.0  0.0   0:00.00 __thr1
126195 xxxxxxx+  20   0  305948   7972   2244 S  0.0  0.0   0:00.00 __thr2

####

多亏了@ikegami,我找到了一个可行的解决方案。

为了使子线程保持活动状态,需要进行一些小的更改,并且还需要阻止主线程将它们重新连接起来。(根据它的行为方式,我假设如果子线程到达它们生成的子线程的末尾,它们将被完全终止,Linux 会清理它们 - 即使主线程尚未调用它们join

对于将来阅读此页面的任何其他人,我很想知道为什么pstree,ps和top中的每一个都显示不同的结果。

无论如何,将此信息和比较留在这里,以防对其他人有所帮助。

最终结果:

  • 使用ps命令,似乎无法获取线程的修改名称。它仅显示触及 $0 的最后一个线程将其设置为的字符串
  • 同样,使用 pstreepstree -p -a -l 144741也只显示主线程作为每个子线程的名称,并且不显示有关线程所做的更改的任何内容。
  • 但是,非常幸运的是,使用顶级作品!!!top -H -b -p 180547,它清楚地显示了主线程,以及所有子线程,它们使用 $0 设置的名称

来自ps的例子:

app_sy+ 180547 131203 180547  0    3 18:08 pts/1    00:00:00 thr2
app_sy+ 180547 131203 180548  0    3 18:08 pts/1    00:00:00 thr2
app_sy+ 180547 131203 180549  0    3 18:08 pts/1    00:00:00 thr2

使用 pstree 的示例:

test.pl,180547
|-{test.pl},180548
`-{test.pl},180549

获胜者使用top -n 1 -H -b -p 180547,它显示了每个线程成功应用于 $0 的不同名称!!!!!

top - 18:00:08 up 69 days,  8:53,  3 users,  load average: 4.10, 3.95, 4.05
Threads:   3 total,   0 running,   3 sleeping,   0 stopped,   0 zombie
%Cpu(s):  7.7 us, 33.5 sy,  0.0 ni, 58.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 13144056+total,  1351640 free, 45880316 used, 84208608 buff/cache
KiB Swap: 16777212 total, 16777212 free,        0 used. 78196224 avail Mem
PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
180547 app_+     20   0  299572   7152   2144 S  0.0  0.0   0:00.00 test.pl
180548 app_+     20   0  299572   7152   2144 S  0.0  0.0   0:00.02 thr1
180549 app_+     20   0  299572   7152   2144 S  0.0  0.0   0:00.01 thr2

在此处添加池上代码的修改版本,供查看此页面的其他人将来参考,保存为 test.pl:

#!/usr/bin/perl
use strict;
use warnings;
use feature qw( say );
use threads;
use threads::shared;
my $phase :shared = 0;
my $main_pid = $$;
sub advance {
lock $phase;
++$phase;
cond_signal($phase);
}
sub wait_for {
lock $phase;
cond_wait($phase) while $phase != $_[0];
}
sub advance_and_wait_for {
lock $phase;
++$phase;
cond_signal($phase);
cond_wait($phase) while $phase != $_[0];
}
my $thr1 = async {
my $id = 'thr1';
wait_for(0);
advance_and_wait_for(2);
say "[$id] Setting $0 to $id.";
$0 = $id;
say "[$id] $0 = $0";
print `ps -eLf|grep $main_pid` =~ s/^/[$id] /mrg;
advance_and_wait_for(4);
say "[$id] $0 = $0";
advance();
while(1){
sleep 1;
}
};
my $thr2 = async {
my $id = 'thr2';
wait_for(1);
advance_and_wait_for(3);
say "[$id] $0 = $0";
say "[$id] Setting $0 to $id.";
$0 = $id;
say "[$id] $0 = $0";
print `ps -eLf| grep $main_pid` =~ s/^/[$id] /mrg;
advance();
while(1){
sleep 1;
}
};
sleep 5;
print "Main thread pid is $main_pid - and $0 is ($0)n";
my $waitfor = <STDIN>;
$_->join for $thr1, $thr2;

最新更新