Unix C multi-process programming

zhaozj2021-02-16  59

Written in front

This article is mainly based on the programming practical experience on UNIX systems, as yourself

Partial summary of programming practices during a period of time, can also become an article. For the Unix programmer beginner

Said a small experience, for reference only; if you don't have a good value for UNIX, please refer to you.

teach.

I. Features of multi-process procedures

Since the UNIX system is a ticed multi-user system, the CPU is allocated to each user by the time film, but

Essentially should be said that the CPU is allocated to each process by time, and each process has its own operating environment.

To make it do not "forget" when the CPU is switched, half of "semi-finished products" have been calculated. Take DOS

The concept, the process of switching is a "DOS Interrupt" processing, including three levels:

(1) Save of user data: including the text section (Text), data segment (DATA, BSS), stack segment

(Stack), the saving memory of the survival section (SHARED MEMORY).

(2) Save of register data: including PC (Program Counter, pointing to the next point to execute)

The address of the order), PSW (Processor Status Word, Processor Status), SP (Stack

Pointer, Stack Pointer), PCBP (Pointer of Process Control Block, Process Control

Block pointer), FP (Frame Pointer, pointing to the first place of Local variables in the stack

Site), AP (AUGUMENT POINTER, pointing to the function called in the stack), ISP (

Interrupt Stack Pointer, interrupt stack pointer), and other universal registers, etc.

(3) Saving of system level: including Proc, U, Virtual Storage Space Management Table, Interrupt Processing Stack.

In order to get the CPU time slice again at once, it can run.

Since the system has handled all of these interrupt processes, what should we do?

What about my heart? We can use the multi-process feature provided by the system, let several programs cooperate sincerely.

Single and efficiently give it a result.

In addition, UNIX system itself is also written with C language, multi-process programming is the Unix

Point, when we are familiar with multi-process programming, we will have a deeper understanding of the UNIX system mechanism.

First of all, I will introduce some of the highlighted features of the multi-process program:

Parallelization

A complex event is to decompose into a number of simple events, this is in programmers

This concept has been formed in the brain, first breaking the problem into a small problem, will ask

Re-subdivision, finally made a function on a suitable scale. In software engineering is also this

What is said. If we think about the way, some small problems can be interfered with each other.

, Can be handled at the same time, and in the key point, it is necessary to be unified in one place, so that the program

The operation is parallel, at least from the people's time concept. And each small problem

The calculation is more simple.

2. Simple and orderly

Such procedures are not sub-management of programmers, and programmers design for each process.

Good function, and combine them with a certain communication mechanism, for each

The process of the process is simple, only carefully cope with the total control part (it is also quite simple),

Complete the construction of the entire program.

3. Done interference

This feature is the characteristics of the operating system, and each process is independent and will not be critical.

4. Serialization

For example, in a data phone query system, it is designed into a process only.

The query can be completed. That is to complete a transaction. When the phone query starts, the process is generated to deal with

This query; when another phone comes in, the master program produces such a process to deal with, each

After completing the query task, it disappears. This programming is more simple, as long as you do a query program

Yes.

Two. Common multi-process programming system calls

Fork ()

Function: Create a new process.

Syntax: #include

#include

PID_T fork ();

Description: This system calls generate a new process, called a sub-process, a complex to call the process.

Products. Calling process is called the father process, and the child process inherits almost all of the parent processes.

Sex:

UID, GID and effective UID, GID.

Environment variable.

Additional GID.

. Close sign when calling exec ().

UID Settings Mode Bits.

GID Setting the mode bit.

Process group number.

Session ID.

Control terminal.

Current working directory.

. Root directory.

. File creates mask umask.

. File length limits ULIMIT.

Predepending value, such as priority and any other process predetermined parameters, according to the species

Decide if it can be inherited.

There are still some other properties.

But the child process also has different properties with the parent process:

The process number, the sub-process number is different from any one of the activities process group number.

Parent process number.

The child process inherits the file descriptor or flow of the Parent process, has a copy of your own

And share this resource with the parent process and other sub-processes.

The user time and system time of the child process are initialized to 0.

The timeout clock of the child process is set to 0.

The signal processing function pointer of the child process is set.

The child process does not inherit the record lock of the Parent process.

Return Value: The call is successful, returning the child process, returning the child process number for the parent process, which is also

The most convenient way to distinguish the father and son process. If the call is fails, return -1 to the parent process,

The child process does not generate.

Example: PID_T PID;

IF ((PID = fork ())> 0) {

/ * Parent Process Process * /

}

Else IF (pid == 0) {

/ * Sub process processing process * /

EXIT (0); / * Attention The child must be run with exit () to exit * /

}

Else {

Printf ("fork error / n");

exit (0);

}

2.system ()

Function: Generate a new process, the child process executes the specified command.

Syntax: #include

#include

Int system (string)

CHAR * STRING;

Explanation: This call passes the parameter string to a command interpreter (generally sh), ie

String is interpreted as a command, executed by the SH. If the parameter string is one

An empty pointer is to check if the command interpreter exists.

This command can be the same as the command line command, but due to the command as a parameter

In the system call, you should pay attention to the processing of special meaning characters when compiling.

Looking is the definition of Path environment variable. The consequences of the commands generally will not be pairs

The process has affected.

Return Value: When the parameter is an empty pointer, the return value is only non-zero when the command interpreter is valid.

If the parameter is not an empty pointer, the return value is the return status of the command (with WaitPid ())

Return value. The command is invalid or syntax error returns a non-zero value, and the command executed is

Term. Other situations returns -1.

Example: char command [81];

INT I;

For (i = 1; i

Int Execl (Path, Arg0, ..., Argn, ​​(char *) 0)

CHAR * PATH, * ARG0, ..., * argn

Int Execv (Path, Argv)

CHAR * PATH, * Argv [];

INT EXECLE (Path, Arg0, ..., Argn, ​​(char *) 0, ENVP)

Char * path, * arg0, ..., * argn, * envp [];

Int Execve (Path, Argv, Envp)

CHAR * PATH, * Argv [], * envp [];

Int Execvp (File, Argv)

Char * file, * argv [];

Description: This is a system called family that is used to transfer a new program into the process.

To save, and override, generate new memory process images. The new program can be executable

Document or shell batch command.

When the C program is executed, it is called:

Main (int Argc, char * argv [], char * envp [];

Argc is the number of parameters, which is the array of various parameter string pointers, and ENVP is the new process.

The array of pointers in the crux string .argc is at least 1, and Argv [0] is the program file name.

So, in the above EXEC system call family, Path is the path name of the new process file.

File is the new process file name, if File is not a full path name, the system call will press PATH ring.

Automatically find the corresponding executable run. If the new process file is not a

Execlp () and Execvp () will be executed (such as batch file)

The file content forms system () as a standard input of a command interpreter.

Arg0, ... et al. indicate the end of '/ 0' end, constitute a valid parameter of the new process, and the parameter list ends with an empty pointer. In turn, arg0 must have at least

To the new process file name or path name.

Similarly, Argv is a string pointer array, argv [0] points to the new process file name or path

Name, and end with an empty pointer.

ENVP is a string pointer array, ending with an empty pointer, and these strings form new

Cheng's environment.

The files opened before calling these system calls are also open for new processes.

Unless it has defined a Close-ON-EXEC logo. Opened file pointers in the new process

Keep the same, all related file locks are also retained.

The calling process settings are being recovered in the new process to the default settings in the new process.

Others remain unchanged.

The UID and GID of the SUID and SGID settings defined by the file when the new process starts.

Effect UID and GID.

The new process also inherited the following properties:

Additional GID.

Process number.

Parent process number.

Process group number.

Session.

Control terminal.

The ALARM clock signal remains.

Current working directory.

. Root directory.

The file creates a mask.

Resource limit.

Time, system time, child process user time, child process system time.

Record lock.

Process signal mask.

Signal shield.

. priority.

A predetermined value.

After the call is successful, the system calls the latest access time to modify the new process file.

Return value: The system call generally does not have a successful return value, because the original process has disappeared

Save.

Example: Printf ("Now this process will be ps command / n");

Execl ("/ Bin / PS", "PS", "- EF", NULL);

4.Popen ()

Function: Initialize the pipeline from / to a process.

Syntax: #include

FILE * POPEN (Command, Type)

Char * command, Type;

Description: This system calls creates a pipe between calling processes and executed commands.

The parameter command is as a command line executed. TYPE is as I / O mode, "R" is from being

Execute the command read, "W" is written to the executed command. Return to a standard stream pointer, as a tube

Road descriptor, read or write data to the executed command (as a stdin that is executed command or

STDOUT) This system call can be used to call the system command in the program and obtain commands

Output information or enter information to the command.

Return Value: NULL is returned, and it returns to the file pointer of the pipe.

5.pclose ()

Function: Close to a process of a process.

Syntax: #include

Int PClose (STRM)

File * STRM;

Note: This system calls for closing the pipes opened by popn () and will wait by POPEN ()

After the activated command is executed, the command return code is read after closing the pipe.

Return Value: Returns -1 if the file descriptor is not opened by POPEN ().

Example: Printf ("Now this Process Will Call Popen System Call / N");

File * fd;

IF ((FD = POPEN ("PS-EF", "R")) == null) {

Printf ("Call Popen FaileD / N);

Return;

}

Else {

Char Str [80];

While (FGETS (STR, 80, FD)! = null)

Printf ("% S / N", STR);

}

PCLOSE (FD);

6.wait ()

Function: Waiting for a child process to return and modify the status

Syntax: #include

#include

PID_T WAIT (STAT_LOC)

INT * STAT_LOC;

Description: Allows the status information of the process to get the child process. The calling process will hang up until it

A child process is terminated.

Return Value: When a child process is returned, the return value is the sub-process number, otherwise the return value is

-1. At the same time, the return value of the STAT_LOC returns the child process.

Example: / * Parent Process * /

IF (fork ()> 0) {Wait (INT *) 0);

/ * The parent process is waiting for the sub-process back * /

}

Else {

/ * Sub process processing process * /

exit (0);

}

7.WaitPid ()

Function: Waiting for the return and modification of the child process of the specified process number

Syntax: #include

#include

PID_T WAITPID (PID, STAT_LOC, OPTIONS)

PID_T PID;

INT * STAT_LOC, OPTIONS;

Description: When the PID is equal to -1, Options is equal to 0, the system call is equivalent to Wait (). Otherwise

The behavior of the system call is determined by the parameter PID and Options.

PID specifies a group of parent processes that require a child process that knows its status:

-1: Requires the return status of any child process.

> 0: The state of the sub-process that needs to know the process number is the PID value.

0) {

WaitPid (PID, & stat_loc, 0);

/ * The parent process waits for the processes of the process number to PID * /

}

Else {

/ * Process of child processes * /

Exit (1);

}

/ * Parent Process * /

Printf ("STAT_LOC IS [% D] / N", STAT_LOC);

/ * String "STAT_LOC IS [1]" will be printed * /

8.setpgrp ()

Function: Set the process group number and session number.

Syntax: #include

PID_T setPGRP ()

Note: If the callout process is not the first process. Set the process group number and the session number to with it.

The process number is equal. And release the control terminal of the transfer process.

Return Value: After the call is successful, return to the new process group number.

Example: / * Parent Processing * /

IF (fork ()> 0) {

/ * Parent process processing * /

}

Else {

setpgrp ();

/ * The process group number of the child process has been modified to be the same as its process number * /

exit (0);

}

9.exit ()

Function: Termination Process.

Syntax: #include

Void EXIT (STATUS)

Int status;

Description: The calling process is terminated by the system call. Cause additional processing is terminated before the process is terminated

The part ends.

Return value: no

10.Signal ()

Function: Signal Management

Syntax: #include

Void (* Signal (SIG, DISP)) (INT)

Int Sig;

Void (* DISP) (INT);

Void (* SigSet (SIG, DISP)) (INT)

Int Sig;

Void (* DISP) (INT);

Int Sighold (SIG)

Int Sig;

Int Sigrelse (SIG)

Int Sig;

Int Sigignore (SIG)

Int Sig;

Int Sigpause (SIG)

Int Sig;

Note: These system calls provide a simple signal processing for the application to the specified signal.

Signal () and SIGSET () are used to modify signal positioning. Parameter SIG specifies signals (except

Sigkill and SigStop, these two signals are processed by system, and the user program cannot capture.

Disp Specifies the new signal positioning, namely the new signal processing function pointer.

SIG_IGN, SIG_DFL or signal handle address.

If SIGNAL (), DISP is the signal handle address, SIG cannot be SIGILL, SigTrap

Or SIGPWR, when the signal is received, the system first resets the signal handle of the SIG as SIG_DFL.

The signal handle is then executed.

If SIGSET (), DISP is the signal handle address, the system will first

The signal is added to the signal mask of the calling process, then execute the signal handle. When the signal handle

Run

After that, the system will recover the signal mask of the calling process to receive the status before the signal is received. In addition,

When using SigSet (), the DISP is SIG_HOLD, the signal will join the calling process.

The positioning of the signal is unchanged in the signal mask.

SIGHOLD () adds the signal to the signal mask of the calling process.

Sigrelse () Remove the signal from the signal mask of the calling process.

Sigignore () Sets the positioning of the signal to Sig_ign.

Sigpause () Remove the signal from the signal mask of the calling process while hangs

The process until the signal is received.

If the signal SIGCHLD is positioned as SIG_IGN, the child process that calls the process is ending

Don't turn into a zombie process stop. The calling process doesn't have to wait for the child process to return and do

Should be treated.

Return Value: The call is successful, Signal () returns the value of the DISP recently called Signal () setting.

Otherwise returns SIG_ERR.

Example 1: Set the user's own signal interrupt processing function, as an example of SIGINT signal:

INT FLAG = 0;

void myself ()

{

FLAG = 1;

Printf ("Get Signal Sigint / N");

/ * To reset the SIGINT signal interrupt processing function is executed for this function

* Next step * /

Void (* a) ();

a = myself;

Signal (SIGINT, A);

FLAG = 2;

}

Main ()

{

While (1) {

Sleep (2000); / * Wait for interrupt signal * /

IF (Flag == 1) {

Printf ("SKIP System Call Sleep / N);

exit (0);

}

IF (Flag == 2) {

Printf ("SKIP System Call Sleep / N);

Printf ("Waiting for Next Signal / N);

}

}

}

11.kill ()

Function: Send a signal to one or a set of processes.

Syntax: #include

#include

INT KILL (PID, SIG);

PID_T PID;

Int Sig;

Explanation: This system call sends a signal to one or a set of processes, which is referred to by the parameter SIG.

Declaration, one of the signal sheets given in the system. If 0 (empty signal) checks the error but

In fact, there is no signal to check the validity of the PID.

PID specifies the process or process group that will be transmitted. If it is more than 0, the signal will

The process sent to the process number equal to the PID; if the PID is equal to 0, the signal will be sent to the

Some of the process of sending signals in a process group (the special process of the system is divided

Outside); if the PID is less than -1, the signal will be sent to all process group numbers and PID absolute values.

The same process; if the PID is equal to -1, the signal will be sent to all processes (special

Except for the process of the process).

The signal is to be sent to the specified process, first calling the process must have a letter to the process

No. Permissions. If there is a right priority of the process, there is permission. If the process is called

The actual or effective UID is equal to the actual UID of the process of receiving the signal or uses setuid ()

The system calls the UID, or SIG equal to Sigcont to send and receive sessions of the process at the same time.

The same is the same, then the calling process also has permission to send the signal.

If the process has the permissions of any one of the processes specified by the signal to the PID, the call is successful.

Otherwise, the call failed, no signal is sent.

Return Value: Returns 0 successfully, otherwise returns -1.

Example: Suppose the previous example process number 324, now send a sigint signal, let it do

Signal processing:

Kill ((PID_T) 324, SIGINT;

12.Alarm ()

Function: Set the timeout clock for a process.

Syntax: #include

Unsigned int Alarm (SEC)

Unsigned int sec;

Description: Indicates the timeout clock of the calling process to send a call process after the specified time.

SIGALRM signal. Setting the timeout clock time value will not be placed in the stack, then once

The setting will rush the previous (not until the timeout time).

If the sec is 0, cancel any previously set timeout clock.

Fork () will initialize the timeout clock of the new process into 0. When a process is exec ()

When the new execution file calls new execution file, the timeout clock set before calling is still

effective.

Return Value: Returns the last time the time left when the timeout clock is set.

Example: int FLAG = 0;

void myself ()

{

FLAG = 1;

Printf ("Get Signal SigalRM / N);

/ * To reset the SIGALRM signal interrupt processing function is executed for this function

* The following steps * /

Void (* a) ();

a = myself;

SIGNAL (SIGALRM, A); FLAG = 2;

}

Main ()

{

ALARM (100); / * 100 seconds post timeout interrupt signal * /

While (1) {

Sleep (2000); / * Wait for interrupt signal * /

IF (Flag == 1) {

Printf ("SKIP System Call Sleep / N);

exit (0);

}

IF (Flag == 2) {

Printf ("SKIP System Call Sleep / N);

Printf ("Waiting for Next Signal / N);

}

}

}

13. msgsnd ()

Function: Send messages into the specified message queue.

Syntax: #include

#include

#include

INT MSGSND (MSQID, MSGP, MSGSZ, MSGFLG)

Int msqid;

Void * msgp;

SIZE_T MSGSZ;

Int msgflg;

Description: Send a message to the message queue that is specified by the MSQID.

Parameters MSGP points to a user-defined buffer, and the first domain of the buffer should

For long integer, specified message type, other data in the message in the buffer

During the area. The following is the message element definition:

Long mtype;

Char mtext [];

MTYPE is an integer for receiving the process selection message type.

MTEXT is any text of a length of MSGSZ bytes, and the parameter MSGSZ can be from 0 to

The maximum intervals of the allowed value change.

MSGFLG Specifies the action behavior:

If (MSGFLG & IPC_NOWAIT) is true, the news is not sent immediately and calls

The process will return immediately.

If (MSGFLG & IPC_NOWAIT) is not true, the calling process will be hung up until

One of the faces happened:

* The message is sent out.

* Message Queue Sign is deleted by the system. The system call returns -1.

* The calling process receives an unloaded interrupt signal, the calling process continues

Execution or termination.

After the call is successful, the relevant structure corresponding to the specified message queue is as follows:

The message number (MSG_QNUM) plus 1.

The message queue recently transmits the process number (MSG_LSPID) to call the process number.

The message queue transmission time (msg_stime) is changed to the current system time.

The above information can be seen using the command ipcs -a.

Return Value: Returns 0, otherwise returns -1.

14.msgrcv ()

Function: Take a message from the message queue.

Syntax: #include

#include

#include

INT MSGRCV (MSQID, MSGP, MSGSZ, MSGTYP, MSGFLG)

Int msqid;

Void * msgp;

Int msgsz;

Long msgtyp;

Int msgflg;

Explanation: This system call reads a message from MSGTYP from the message queue specified by MSQID.

The type of message is in the buffer pointed to by MSGP, the structure of the buffer is like

Note, including message type and message body. Msgsz is the text of the received message

Number of bytes. If the length of the message received is greater than Msgsz, it will be truncated.

Msgsz byte (when the message logo msgflg & msg_noerror is true), cut off

Some will be lost and the message transmission process is not notified.

MSGTYP Specifies Message Type:

To 0 receive the first message in the message queue.

More than 0, the first type of MSGTYP is received in the message queue.

. Less than 0, the first type value in the receive message queue is not less than the absolute value of MSGTYP and

Messages whose types are smaller.

MSGFLG Specifies the action behavior:

If (MSGFLG & IPC_NOWAIT) is true, the calling process will return immediately, if not

The returned value is -1, and errno is set to eNomsg.

If (MSGFLG & IPC_NOWAIT) is not true, the calling process will be hung up until

One of the faces happened:

* The type of message in the queue is valid.

* Message Queue Sign is deleted by the system. The system call returns -1.

* The calling process receives an unloaded interrupt signal, the calling process continues

Execution or termination.

After the call is successful, the relevant structure corresponding to the specified message queue is as follows:

The number of messages (MSG_QNUM) minus 1.

The message queue recently received the process number (MSG_LRPID) to call the process number.

The message queue receive time (MSG_RTIME) is changed to the current system time.

The above information can be seen using the command ipcs -a.

Return Value: The return value is equal to the number of bytes that receive the actual message body.

Returns -1 is returned in unsuccessful.

15. msgctl ()

Function: Message Control

Syntax: #include

#include

#include

INT MSGCTL (MSQID, CMD, BUF)

INT MSQID, CMD;

Struct MSQID_DS * BUF;

Description: This system call provides a series of message control operations, and the operation action is defined by the CMD, below

The CMD definition value indicates the definition of each operating action.

. IPC_STAT: Put the current value of each element in the data structure related to the MSQID

BUF points to the structure.

. IPC_SET: Set the following elements in the data structure related to the MSQID to BUF

The corresponding value in the structure.

MSG_Perm.uID

MSG_Perm.gid

MSG_Perm.Mode

MSG_QBYTES

This command can only be equal to MSG_Perm.cuid or MSG_Perm.UID by a valid UID.

Process or valid UID process operations with appropriate permissions. Only with appropriate permissions

Users can increase the value of MSG_QBYTES.

. IPC_rmid: Delete the message queue indicated by MSQID. Delete it from the system and

Destroy the relevant data structure.

This command can only be equal to MSG_Perm.cuid or MSG_Perm.UID by a valid UID.

Process or valid UID process operations with appropriate permissions.

Return Value: The return value is 0, otherwise it is -1.

16.msgget ()

Function: A message queue is obtained.

Syntax: #include

#include

#include

INT MSGGET (key, msgflg)

Key_t key;

Int msgflg;

Description: This system calls return the identifier of the message queue related to the parameter key.

If the following fact is established, the identifier and data structure associated with the message queue will be created.

Built out:

If the parameter key is equal to IPC_Private.

If the parameter key does not have an existing message queue identifier, the value is

(Msgflg & IPC_CREAT) is true.

When you create a message queue, the data structure associated with the new message queue identifier will be

As follows:

. MSG_Perm.cuid and MSG_Perm.uid are set to the valid UID of the calling process.

Msg_perm.cgid and msg_perm.gid are set to the valid GID of the calling process.

. MSG_Perm.Mode Access Permissions Bits are set to MSGFLG access ratios.

. MSG_QNUM, MSG_LSPID, MSG_LRPID, MSG_stime, MSG_RTIME set to 0.

. MSG_cTime is set to the current system time.

. MSG_QBYTES is set to the maximum allowed by the system.

Return Value: Returns a non-0 value, called a message queue identifier; otherwise the return value is -1.

Example: This example will include system calls that include all message queues described above:

#define rkey 0x9001L / * Key value * /

#define WKey 0x9002L / * Key value * /

#define msgflg 0666 / * Message Queue Access * /

#define ipc_wait 0 / * Waiting method is not defined in the include file * /

INT RMSQID; / * Read Message Queue Identifier * /

INT WMSQID; / * Write Message Queue Identifier * /

Struct msgbuf {

Long mtype;

Char mtext [200];

} BUF;

/ * If the read message queue has existed, the identifier is obtained, otherwise it is created and obtained the identifier * /

IF ((rmsqid = msgget (rkey, msgflg | ipc_creat)) 0)

Printf ("Get% LD Type Message from Queue:% S / N",

转载请注明原文地址:https://www.9cbs.com/read-19691.html

New Post(0)