1. Perl
  2. Interprocess communication

Interprocess communication

I will explain how to perform "interprocess communication" in Perl.

What is a process

A process is a unit of resource management as seen from the OS. Processes are assigned a unique process ID for the OS, resources include file handles, memory space, and CPU. From the user's point of view, a process is a program that is running.

Image of OS process management

   Image of event OS process management
                            | - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
                            | Determine process ID (3452) |
| - -- -- -- -- -- - | | |
| Program execution started | - -- -->| Memory allocation management |
| - -- -- -- -- -- - | | Reserve a certain amount of memory space for the process, |
                            | Manage by process ID |
                            | (The allocated memory area, |
                            | Do not interfere with other processes) |
                            | |
                            | Read the executable code into memory. |
                            | Allocate a static data area in memory. |
                            | |
                            | CPU allocation management |
                            | Process ID to schedule CPU allocation |
                            | Register. |
                            | - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |

                            | - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
| - -- -- -- -- -- - | | In response to process file open request |
| Open file | - -- -->| Open file |
| - -- -- -- -- -- - | | Manage open files by process ID |
                            | - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |

                                A process is a memory, a file, as seen from the OS.
                              A unit for managing CPU scheduling.

$$ - Get process ID

Use the predefined variable " $$" to get the process ID.

$$

The process ID is an identifier assigned when the process is started so that the OS can uniquely identify the process.

$^T - Get the process start time

Use the predefined variable " $^T " to get the start time of the process.

$^T

The time is obtained in epoch seconds (seconds from 00:00:00 on January 1, 1970).

fork function

You can use the fork function to branch a process into two . One forked process is the parent process and the other is the child process.

The fork function takes no arguments. The return value will be the process ID of the branched child process if the branched process is the parent process. 0 for child processes. If fork fails, undef is returned.

my $pid = fork;

For the fork function, see "fork function".

wait function

If you branch with fork, you don't know which of the parent and child processes will terminate first. This time, I will explain how the parent process waits for the child process to finish.

Use the wait function to wait for the child process to terminate. The wait function waits until one child process terminates . The return value is the process ID of the terminated child process . If the child process was automatically reclaimed for any reason, -1 will be returned.

my $pid = wait;

For the wait function, see "wait function".

$? - Child process exit status

If wait waits for the child process to terminate, the predefined variable "$?" Stores multiple values including the exit status of the child process. $? Is also set when a child process is executed using the system function.

Exit status of child process ***

The method of interpreting $? Is a little complicated. $? Is set to a 16-bit value. The exit status of the child process is set to the upper 8 bits . The 8th bit of the lower 8 bits indicates whether a core dump was generated . The lower 8 bits up to the 7th bit represent the signal number that terminated the process , if any.

For more information on the predefined variable "$?", See "See the list of" predefined variable "in Perl". Please give me.

Describe the process of releasing the resource of the child process

To release the resources of the child process, use the waitpid function and write the following.

use POSIX 'WNOHANG';
$SIG{CHLD} = sub {while (waitpid (-1, WNOHANG)> 0) {Resource release process}}

I think it is difficult to understand the meaning of this description at first glance, so I will explain it.

CHLD signal

The CHLD signal is a signal sent to the parent process when the child process terminates. In other words, by monitoring the CHLD signal on the parent process side, you can do something when the child process terminates.

$SIG{CHLD} = sub {What to do if a child process terminates}

waitpid function

The waitpid function waits until the child process with the specified process ID changes state. There are three state changes:

  1. Child process terminated
  2. Child process stopped
  3. Child process resumed

If there is a state change, the watipid function returns the process ID of its child process. Also, when the child process terminates, it releases the process in the zombie state. A zombie state is a state that has been terminated but has not been removed from the OS process table.

The first argument of the waitpid function is the ID of the child process, but if you specify -1, you can check one state change of any child process. WNOHANG is an option to prevent blocking if there are no child processes with state changes.

If waitpid succeeds, it returns the process ID of the child process whose state has changed. If WNOHANG is specified and one or more of the specified child processes exist, but no state change has occurred in any of the child processes, 0 is returned. Returns -1 on error.

I tried to extract only the call part of waitpid.

waitpid (-1, WNOHANG)

Let's summarize this.

  1. If any of the child processes have changed state, the process ID (greater than 0) is returned, and if the child process has terminated, the zombie state process is released. (Since it is set as a handler for the CHLD signal this time, you can think of it as "returning the process ID and releasing the zombie-state process if any of the child processes are terminated")
  2. If no child process exists, an error will occur and -1 will be returned.
  3. If one or more of the specified child processes exist, but no state change has occurred in any of the child processesReturns 0.

Therefore, if you describe the condition that the return value is greater than 0 as shown below, you can describe the processing to be executed when any of the child processes is terminated.

if (waitpid (-1, WNOHANG)> 0) {
  # ...
}

While loop

while (waitpid (-1, WNOHANG)> 0) {Resource release process}

Looking at this part, you may wonder why you need while statement. If one CHLD signal is sent when one child process terminates, it's natural to think that while statement isn't needed. However, there is one constraint on the signal, and if multiple child processes are terminated in a very short time, the signal will be overwritten and even though multiple child processes are terminated. , It is possible that only one signal can be sent.

To do this, you need to use while statement to process all terminated child processes.

If you don't need any specific action and just want to release the zombies

If you don't need to release a specific resource and just want to release a zombie, you can set "IGNORE" without calling waitpid from the signal hands and it will do it automatically.

$SIG{CHLD} = 'IGNORE' ;

Read the output of other commands using a pipe

A mechanism called a pipe is used to read the output of other commands.

use strict;
use warnings;

# (1) Open a pipe to read the output of other commands
open my $pipe, '-|', 'dir'
  or die qq/Can't open pipe:$!/;

# (2) Read from pipe
while (my $line = <$pipe>) {
  print $line;
}

close $pipe;

(1) Open a pipe to read the output of other commands

open my $pipe, '-|', 'dir'
  or die qq/Can't open pipe:$!/;

The open function has special uses. To open a pipe that receives the output of other commands, specify "-|" in the second argument and the command in the third argument. This time, "dir", which is a command to output the contents of the directory, is specified.

Imagine replacing the hyphen part of the "-|" in the second argument with a command and the output of another command flowing through the pipe.

dir | perl

(2) Read from pipe

while (my $line = <$pipe>) {
  print $line;
}

I'm reading line by line from the pipe. Notice that from the program's point of view, it looks like it's reading from a file.

Pass the output to other commands using a pipe

To pass the output to another command, use a mechanism called a pipe.

use strict;
use warnings;

# (1) Open a pipe to send output to other commands
open my $pipe, '|-', 'more'
  or die qq/Can't open pipe:$!/;

# (2) Write to pipe
print $pipe "Hello world";

close $pipe;

(1) Open a pipe to send output to other commands

open my $pipe, '|-', 'more'
  or die qq/Can't open pipe:$!/;

The open function has special uses. To open a pipe that receives the output of other commands, specify "|-" in the second argument and the command in the third argument. This time, "more", which is a command to output the contents of the file, is specified.

Replace the hyphen part of the second argument "|-" with a command, and imagine the output flowing into the command.

Output | more

(2) Write to pipe

print $pipe "Hello world";

When writing to a pipe, the output result is passed to another command. Notice that from the program's point of view, it looks like it's writing to a file.

getpwuid function - get user information (user name)

To get the username , use getpwuid function and the predefined variable $> below will do so.

my $user = getpwuid($>);

You can get the user name by specifying the user ID in the argument of getpwuid.

getpwnam function - get user ID from username

To get the user ID from the username , use getpwnam function and do the following:

# Get user ID from user name
my $uid = (getpwnam'ken') [2];

getgrnam function - get group ID from group name

To get the group ID from the group name , use getgrnam function as follows.

# Get group ID from group name
my $gid = (getgrnam'devel') [2];

Related Informatrion