When you give the shell a command line to execute, the shell usually creates a new process to execute the command. This new process becomes a child of the shell, executing independently, yet coordinating with the shell. Similarly, a Perl program can launch new processes, and like most other operations, has more than one way to do so.
Process management is the fancy name for getting programs to ‘talk’ to each other, keeping track of what a program is doing, keeping track of the children spawned, etc.
The System Function
The simplest way to launch a child process in Perl to run a program is the system function. This function creates a new process, runs a program in it and waits for its completion. It returns the Termination Status of the program.
For example, to invoke the Unix date command from within Perl, it looks like:
system "date";
The child process runs the date command, which inherits Perl’s standard input, standard output, and standard error. This mean that the normal short date-and-time string generated by date ends up wherever Perl’s STDOUT was already going. The parameter to the system function is generally whatever you’d normally type at the shell.
The exec Function
Everything we’ve just said about system function is also true about the exec function, except for one (very important) thing. The system function creates a child process, which then scurries off to perform the requested action while Perl naps. The exec function causes the Perl process itself to perform the requested action. Think of it as more like a "goto" than a subroutine call.
For example, suppose we wanted to run the bedrock command in the /tmp directory, passing it arguments of -o args1 followed by whatever arguments our own program was invoked with. That’d look like this:
chdir "/tmp" or die "Cannot chdir /tmp: $!"; exec "bedrock", "-o", "args1", @ARGV;
When we reach the exec operation, Perl locates bedrock, and “jumps into it”. At that point, there is no Perl process any more, just the process running the bedrock command. When bedrock is finished, there’s no Perl to come back to, so we’d get a prompt back if we invoked this program from the command line.
If you are puzzling over system versus exec, just pick system, and nearly all of the time, you’ll be just fine.
Process Management – Using fork()
We can clone current processes by issuing the fork command. For example :
if(!defined $kidpid == fork()))
# fork returned undef, so failed
die "Cannot fork: $!";
} elsif ($pid == 0) {
# fork returned 0, so this branch is child
exec("date");
# if exec fails, fall through to the next statement
die "can't exec date: $!";
} else {
# fork returned 0 nor undef
# so this branch is parent
waitpid($kidpid, 0);
}
Multi-process Management
Threads
Since Perl 5.8, thread programming has been available using a model called interpreter threads which provides a new Perl interpreter for each thread, and, by default, results in no data or state information being shared between threads.To use shared variables, you need to also load threads::shared.
use threads;
use threads::shared;
$thr = threads->create(FUNCTION, ARGS);
This will create a new thread that will begin execution with the specified entry point function, and give it the ARGS list as parameters. It will return the corresponding threads object, or undef if thread creation failed. $thr->join() This will wait for the corresponding thread to complete its execution.
When the thread finishes, ->join() will return the return value(s) of the entry point function. threads->exit() if needed, a thread can be exited at any time by calling threads->exit() . This will cause the thread to return undef in a scalar context, or the empty list in a list context. When called from the main thread, this behaves the same as exit(0).
A disadvantage of threads is that Perl needs to be compiled with threads support.
POE
The perl module POE is best known for simulating multiple user threads in a perl application. POE is a Perl framework for reactive systems, cooperative multitasking, and network applications. It is also very useful for managing the forking and managing of child processes. By using POE to handle this, the programmer can stop worrying about correctly handling the forking.
Example :
For this example, we’re going to make a server daemon which accepts TCP connections and prints the answers to simple arithmetic problems posed by its clients. When someone connects to it on port 31008, it will print “Hello, client!”. The client can then send it an arithmetic expression, terminated by a newline and the server will send back the answer.
use Socket qw(inet_ntoa); use POE qw( Wheel::SocketFactory Wheel::ReadWrite Filter::Line Driver::SysRW ); use constant PORT => 31008; Here, we import the modules and functions which the script will use, and define a constant value for the listening port. The odd-lookingqw()
statement after the 'use POE
' is just POE's shorthand way for pulling in a lot ofPOE::
modules at once. new POE::Session ( _start => \&server_start, _stop => \&server_stop, ); $poe_kernel->run(); exit;
We set up the main server session, tell the POE kernel to start processing events, and then exit when it’s done.
POE automatically exports the $poe_kernel variable into your namespace when you write ‘use POE’.