#Perl process management
#Process creation
#fork function
use strict;
use warnings;
my $pid = fork;
if ($pid == 0) {
# 子进程
print "Child process (PID: $$)\n";
sleep 2;
print "Child exiting\n";
exit(0);
} elsif ($pid > 0) {
# 父进程
print "Parent process (PID: $$)\n";
print "Child PID: $pid\n";
waitpid($pid, 0); # 等待子进程结束
print "Child exited\n";
} else {
# fork 失败
die "Cannot fork: $!";
}#exec function
use strict;
use warnings;
my $pid = fork;
if ($pid == 0) {
# 子进程执行其他程序
exec("ls", "-l") or die "Cannot exec: $!";
# exec 不会返回
} else {
waitpid($pid, 0);
print "Executed command\n";
}#system function
use strict;
use warnings;
# 执行命令并返回退出状态
my $status = system("ls -l");
if ($status == 0) {
print "Command succeeded\n";
} else {
print "Command failed with status: $status\n";
}
# 使用列表形式(更安全)
my @command = ("ls", "-l", "/tmp");
$status = system(@command);#Backtick (capture output)
use strict;
use warnings;
# 捕获命令输出
my $output = `ls -l`;
print $output;
# 列表形式
my @output = `ls -l`;
print "Lines: " . scalar(@output) . "\n";
# 使用 qx// 操作符
my $output2 = qx/date/;
print $output2;#Process communication
#Pipe (Pipe)
use strict;
use warnings;
use IPC::Open2;
# 创建管道
my ($read_fh, $write_fh);
pipe($read_fh, $write_fh) or die "Cannot pipe: $!";
my $pid = fork;
if ($pid == 0) {
# 子进程:写入数据
close($read_fh);
print $write_fh "Hello from child\n";
print $write_fh "Second line\n";
close($write_fh);
exit(0);
} else {
# 父进程:读取数据
close($write_fh);
while (my $line = <$read_fh>) {
print "Parent received: $line";
}
close($read_fh);
waitpid($pid, 0);
}#Bidirectional pipeline
use strict;
use warnings;
use IPC::Open2;
my $pid = open2(my $read_fh, my $write_fh, "bc");
# 写入数据
print $write_fh "2 + 2\n";
print $write_fh "10 * 5\n";
print $write_fh "quit\n";
# 读取结果
while (my $line = <$read_fh>) {
print "Result: $line";
}
close($read_fh);
close($write_fh);
waitpid($pid, 0);#Shared memory
use strict;
use warnings;
use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRWXU);
use IPC::SharedMem;
# 创建共享内存
my $shm = IPC::SharedMem->new(IPC_PRIVATE, 1024, IPC_CREAT | S_IRWXU)
or die "Cannot create shared memory: $!";
my $pid = fork;
if ($pid == 0) {
# 子进程写入
$shm->write("Hello from child", 0, 20);
sleep 2;
exit(0);
} else {
# 父进程读取
sleep 1;
my $data = $shm->read(0, 20);
print "Parent read: $data\n";
waitpid($pid, 0);
$shm->remove();
}#Semaphore
use strict;
use warnings;
use IPC::Semaphore;
my $sem = IPC::Semaphore->new(1234, 1, IPC_CREAT | 0666)
or die "Cannot create semaphore: $!";
my $pid = fork;
if ($pid == 0) {
# 子进程:获取信号量
$sem->op(0, -1, 0); # 等待并获取
print "Child acquired semaphore\n";
sleep 2;
print "Child releasing semaphore\n";
$sem->op(0, 1, 0); # 释放
exit(0);
} else {
# 父进程:等待子进程完成
waitpid($pid, 0);
print "Parent done\n";
}
$sem->remove();#Process control
#wait and waitpid
use strict;
use warnings;
my @pids;
# 创建多个子进程
for (1..3) {
my $pid = fork;
if ($pid == 0) {
print "Child $$ running\n";
sleep int(rand(3));
print "Child $$ exiting\n";
exit(0);
} else {
push @pids, $pid;
}
}
# 等待所有子进程
foreach my $pid (@pids) {
my $done_pid = waitpid($pid, 0);
print "Child $done_pid exited\n";
}#kill function
use strict;
use warnings;
my $pid = fork;
if ($pid == 0) {
# 子进程
$SIG{INT} = sub {
print "Child caught INT signal\n";
exit(0);
};
print "Child running\n";
sleep 10;
print "Child done\n";
} else {
# 父进程
sleep 2;
print "Sending INT to child\n";
kill 'INT', $pid;
waitpid($pid, 0);
print "Child exited\n";
}#Process status check
use strict;
use warnings;
my $pid = fork;
if ($pid == 0) {
print "Child PID: $$\n";
sleep 5;
exit(0);
} else {
for (1..3) {
sleep 1;
# 检查进程是否还在运行
my $result = kill 0, $pid;
if ($result) {
print "Child $pid is still running\n";
} else {
print "Child $pid has exited\n";
last;
}
}
waitpid($pid, 0);
}#Signal processing
#Basic signal processing
use strict;
use warnings;
# 设置信号处理器
$SIG{INT} = sub {
print "\nCaught SIGINT\n";
exit(0);
};
$SIG{TERM} = sub {
print "\nCaught SIGTERM\n";
cleanup();
exit(0);
};
sub cleanup {
print "Cleaning up...\n";
# 清理代码
}
print "Running (press Ctrl+C to stop)\n";
while (1) {
sleep 1;
}#Ignore signal
use strict;
use warnings;
# 忽略 INT 信号
$SIG{INT} = 'IGNORE';
print "SIGINT ignored (press Ctrl+C won't work)\n";
sleep 10;
print "Done\n";###Default signal handling
use strict;
use warnings;
# 使用默认处理
$SIG{INT} = 'DEFAULT';
print "SIGINT using default handler\n";
sleep 10;#Practical example
#Example 1: Process Pool
#!/usr/bin/perl
use strict;
use warnings;
sub create_process_pool {
my ($num_workers, $worker_sub) = @_;
my @workers;
for (1..$num_workers) {
my $pid = fork;
if ($pid == 0) {
# 工作进程
while (1) {
$worker_sub->();
}
exit(0);
} else {
push @workers, $pid;
}
}
return \@workers;
}
# 使用
my $workers = create_process_pool(3, sub {
print "Worker $$ processing\n";
sleep 2;
});
# 等待 Ctrl+C
$SIG{INT} = sub {
print "Stopping workers...\n";
kill 'TERM', @$_ for $workers;
waitpid($_, 0) for @$workers;
exit(0);
};
while (1) {
sleep 1;
}#Example 2: Parallel task execution
#!/usr/bin/perl
use strict;
use warnings;
my @tasks = (
{ name => "Task 1", duration => 3 },
{ name => "Task 2", duration => 2 },
{ name => "Task 3", duration => 4 },
{ name => "Task 4", duration => 1 }
);
sub run_task {
my ($task) = @_;
print "Starting $task->{name}\n";
sleep $task->{duration};
print "Completed $task->{name}\n";
}
# 并行执行所有任务
my @pids;
foreach my $task (@tasks) {
my $pid = fork;
if ($pid == 0) {
run_task($task);
exit(0);
} else {
push @pids, $pid;
}
}
# 等待所有任务完成
waitpid($_, 0) for @pids;
print "All tasks completed\n";#Example 3: Daemon process
#!/usr/bin/perl
use strict;
use warnings;
sub daemonize {
# Fork 第一次
my $pid = fork;
exit if $pid;
die "Cannot fork: $!" unless defined $pid;
# 创建新会话
setsid() or die "Cannot setsid: $!";
# Fork 第二次
$pid = fork;
exit if $pid;
die "Cannot fork: $!" unless defined $pid;
# 重定向标准输入输出
open(STDIN, '<', '/dev/null') or die "Cannot redirect STDIN: $!";
open(STDOUT, '>', '/dev/null') or die "Cannot redirect STDOUT: $!";
open(STDERR, '>&STDOUT') or die "Cannot redirect STDERR: $!";
# 信号处理
$SIG{INT} = 'IGNORE';
$SIG{TERM} = sub {
print STDERR "Daemon stopping\n";
exit(0);
};
}
# 使用
daemonize();
my $count = 0;
while (1) {
sleep 5;
$count++;
open(my $fh, '>>', 'daemon.log') or die "Cannot open log: $!";
print $fh "Heartbeat $count at " . localtime() . "\n";
close($fh);
}#Summary
This chapter learns about Perl’s process management:
- ✅ Process creation (fork, exec, system)
- ✅ Process communication (pipeline, shared memory, semaphore)
- ✅ Process control (wait, waitpid, kill)
- ✅ Signal processing
- ✅ Practical examples
Next, we'll study Perl References.