2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
A signal is a software interrupt and a method of passing messages between processes. It is used to notify a process that an event has occurred, but it cannot pass any data to the process.
There are many reasons why signals are generated. In Shell, you can usekill
andkillall
Command to send signal:
kill -信号的类型 进程编号
killall -信号的类型 进程名
Signal name | Signal value | Default processing action | Reason for signaling |
---|---|---|---|
SIGHUP | 1 | A | The terminal hangs or the control process terminates |
SIGINT | 2 | A | Keyboard interrupt Ctrl+c |
SIGQUIT | 3 | C | The keyboard's escape key is pressed |
SIGILL | 4 | C | Illegal instruction |
SIGTRAP | 5 | C | Breakpoint instructions |
SIGABRT | 6 | C | Abort signal issued by abort(3) |
SIGBUS | 7 | C | Bus Error |
SIGFPE | 8 | C | Floating point exceptions |
SIGKILL | 9 | A | kill -9 kills the process. This signal cannot be captured or ignored. |
SIGUSR1 | 10 | A | User defined signal 1 |
SIGSEGV | 11 | C | Invalid memory reference (array out of bounds, operation on null pointer) |
SIGUSR2 | 12 | A | User defined signal 2 |
SIGPIPE | 13 | A | Write data to a pipe with no read process |
SIGALRM | 14 | A | Alarm signal, the signal emitted by the alarm() function |
SIGTERM | 15 | A | Termination signal, the default signal sent |
SIGSTKFLT | 16 | A | Stack Error |
SIGCHLD | 17 | B | Emitted when the child process ends |
SIGCONT | 18 | D | Resume a stopped process |
SIGSTOP | 19 | D | Stop a process |
SIGTSTP | 20 | D | Press the stop button on the terminal |
SIGTTIN | 21 | D | Background process requests to read terminal |
SIGTTOU | 22 | D | Background process requests to write to the terminal |
SIGURG | 23 | B | Emergency condition detection (socket) |
SIGXCPU | 24 | C | CPU time limit exceeded |
SIGXFSZ | 25 | C | Exceeded file size limit |
SIGVTALRM | 26 | A | Virtual clock signal |
SIGPROF | 27 | A | Analyzing clock signals |
SIGWINCH | 28 | B | Window size changes |
SIGPOLL | 29 | B | Polling (Sys V) |
SIGPWR | 30 | A | electricity failure |
SIGSYS | 31 | C | Illegal system call |
A's default action is to terminate the process.
B's default action is to ignore this signal.
The default action for C is to terminate the process and dump the kernel image.
The default action of D is to stop the process. A program that enters the stopped state can be resumed.
There are three ways for a process to handle signals:
signal()
The function can set how the program handles the signal.
Function declaration:
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
Parameter Description:
sig
: Specifies the signal to capture.func
: A pointer to a signal processing function. The processing function needs to receive an integer parameter, which is the captured signal number.SIG_DFL
:SIG_DFL macro indicates the default signal handling method. UseSIG_DFL
Assignal
The second parameter of the function indicates that the system default processing method is used for the signal.SIG_IGN
:SIG_IGN macro means ignore the signal. UseSIG_IGN
Assignal
The second parameter of the function indicates that the process will ignore the signal when it receives it and will not perform any processing. This can prevent the process from being accidentally terminated or interrupted in some cases.SIG_ERR
:SIG_ERR
The macro is used to indicate an error. It is not intended to be used assignal
function, but as the second argumentsignal
The return value of the function indicates that the call failed.signal
If the function fails, it returnsSIG_ERR
This is usually used to detect and processsignal
Error in function call.The service program runs in the background. If you want to terminate it, killing it is not a good idea, because when the process is killed, it dies suddenly and no follow-up work is arranged.
If a signal is sent to the service program, and the service program receives the signal, it calls a function and writes the follow-up code in the function, the program can exit in a planned manner.
Sending a 0 signal to the service program can detect whether the program is alive.
The Linux operating system provides kill
andkillall
Command to send a signal to the program. In the program, you can usekill()
Library functions send signals to other processes.
Function declaration:
int kill(pid_t pid, int sig);
kill()
The function takes parameterssig
The specified signal is passed to the parameterpid
The specified process.
parameter pid
There are several situations:
pid > 0
Send a signal to the processpid
process.pid = 0
Send the signal to all processes in the same process group as the current process. It is often used by the parent process to send signals to the child process. Note that this behavior depends on the system implementation.pid < -1
Send the signal to the process group ID|pid|
All processes.pid = -1
Send the signal to all processes that have permission to send signals, but not including the process that sent the signal.There are 8 ways to terminate a process, 5 of which are normal terminations, which are:
main()
Functionreturn
return;exit()
function;_exit()
or_Exit()
function;return
return;pthread_exit()
return;There are three ways of abnormal termination, they are:
abort()
Function abort;exist main()
In the function,return
The returned value is the termination status.return
Statement or callexit()
, then the termination status of the process is 0.
In Shell, check the status of process termination:
echo $?
3 functions to terminate the process normally (exit()
and_Exit()
is described by ISO C,_exit()
is specified by POSIX):
void exit(int status);
void _exit(int status);
void _Exit(int status);
status
The status of the process termination.
return
Indicates that the function returns and the destructor of the local object is called.main()
In the functionreturn
The destructors of global objects are also called.exit()
It means to terminate the process. The destructor of local objects will not be called, only the destructor of global objects will be called._exit()
and_Exit()
Exit directly without performing cleanup.The process can be used atexit()
Function registration termination functions (up to 32), these functions will beexit()
Automatically called.
int atexit(void (*function)(void));
exit()
Termination functions are called in the reverse order of registration.
system()
The function provides a simple way to execute a program, passing the program to be executed and the parameters to be executed as a string.system()
Function is enough.
Function declaration:
int system(const char * string);
system()
The return value of the function is more troublesome.
system()
The function returns non-zero;system()
The function returns 0;system()
The function returns non-zero.exec
The function family provides another way to call a program (binary file or shell script) in a process.
exec
The declaration of the function family is as follows:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
Notice:
errno
middle.exec
After that, the called program will replace the calling program, that is,exec
No code after the function will be executed.execl()
andexecv()
, others are rarely used.All processes in the entire Linux system are in a tree structure.
usepstree
The command can view the process tree:
pstree -p 进程编号
Each process has a unique process ID represented by a non-negative integer. Although unique, process IDs can be reused. When a process terminates, its process ID becomes a candidate for reuse. Linux uses a delayed reuse algorithm to make the ID of a newly created process different from the ID used by the most recently terminated process. This prevents a new process from being mistaken for a terminated process using the same ID.
Function to get the process ID:
pid_t getpid(void); // 获取当前进程的ID。
pid_t getppid(void); // 获取父进程的ID。
An existing process can callfork()
The function creates a new process.
Function declaration:
pid_t fork(void);
Depend onfork()
The new process created is called a child process.
fork()
The function is called once but returns twice. The difference between the two returns is that the return value of the child process is 0, while the return value of the parent process is the process ID of the newly created child process.
The child process and the parent process continue to executefork()
The following code,The child process is a copy of the parent process. The child process has a copy of the parent process's data space, heap, and stack (note: the child process has a copy, not shared with the parent process).
fork()
After that, the execution order of the parent process and the child process is undefined.
fork()
, let the child process handle these requests, while the parent process continues to wait for the next connection request.fork()
Called immediately after returningexec
。fork()
A feature of is that the file descriptors opened in the parent process are copied to the child process, and the parent process and the child process share the same file offset.
If the parent and child processes write to the same file descriptor without any form of synchronization, their output may be intermixed.
At this point you can see that there are only 100,000 rows of data.
At this point there should be 200,000 lines of data. The lack of one line may be because the file write operation is not atomic. In the absence of a synchronization mechanism, two processes may try to write to different parts of the file at the same time, causing the written data to interfere with each other.
vfork()
Function calls and return values are similar tofork()
Same, but the semantics of both are different.
vfork()
The function is used to create a new process, and the purpose of the new process isexec
A new program that does not copy the address space of the parent process because the child process immediately callsexec
, so the address space of the parent process will not be used. If the child process uses the address space of the parent process, it may bring unknown results.
vfork()
andfork()
Another difference is:vfork()
Ensure that the child process runs first, and then callexec
orexit
The parent process then resumes execution.
In the operating system, a zombie process is a child process that has terminated but whose parent process has not yet read its exit status. Although the zombie process is no longer running, it still occupies an entry in the process table so that the kernel can save the exit status information of the process (such as process ID, exit status, etc.) until the parent process reads this information.
If the parent process exits before the child process, the child process will be hosted by process 1 (this is also a way to let the process run in the background).
If the child process exits before the parent process, and the parent process does not process the child process's exit information, then the child process will become a zombie process.
The kernel retains a data structure for each child process, including the process number, termination status, CPU time used, etc. If the parent process handles the child process exit information, the kernel will release this data structure. If the parent process does not handle the child process exit information, the kernel will not release this data structure, and the child process number will always be occupied. The process numbers available to the system are limited. If a large number of zombie processes are generated, the system will not be able to generate new processes due to the lack of available process numbers.
signal(SIGCHLD, SIG_IGN)
Notify the kernel that it is not interested in the child process's exit, so the child process will release its data structure immediately after exiting.wait()
/waitpid()
function: The parent process waits for the child process to end by calling these functions and obtains its exit status, thereby releasing the resources occupied by the child process.pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
pid_t wait3(int *status, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
The return value is the child process number.
stat_loc
This is the information of the child process termination:
a) If the termination is normal, the macro WIFEXITED(stat_loc)
Return true, macroWEXITSTATUS(stat_loc)
The termination status can be obtained;
b) If the termination is abnormal, the macro WTERMSIG(stat_loc)
Can get the signal to terminate the process.
If the parent process is busy, you can capture SIGCHLD
Signal, called in the signal processing functionwait()
/waitpid()
。
[Sending signals between processes](##1.5 Sending signals)
In a multi-process service program, if the child process receives an exit signal, the child process exits on its own.
If the parent process receives an exit signal, it should send an exit signal to all child processes and then exit itself.
Multiple threads share the address space of the process.If multiple threads need to access the same block of memory, use a global variable.。
In multiple processes, the address space of each process is independent and not shared.If multiple processes need to access the same block of memory, global variables cannot be used, only shared memory can be used。
Shared memory allows multiple processes (without requiring blood relationship between processes) to access the same memory space, and is the most effective way to share and transfer data between multiple processes. Processes can connect shared memory to their own address space. If a process modifies the data in the shared memory, the data read by other processes will also change.
Shared memory does not provide a locking mechanism, that is, when a process reads/writes shared memory, it does not prevent other processes from reading/writing it.If you want to lock the read/write of shared memory, you can use a semaphore. Linux provides a set of functions for operating shared memory.
This function is used to create/get shared memory.
int shmget(key_t key, size_t size, int shmflg);
typedef unsigned int key_t
), usually in hexadecimal, for example 0x5005
, the keys of different shared memories cannot be the same.0666|IPC_CREAT
Indicates that if the shared memory does not exist, create it.use ipcs -m
You can view the system's shared memory, including: key value (key), shared memory id (shmid), owner (owner), permissions (perms), and size (bytes).
use ipcrm -m 共享内存id
You can manually delete the shared memory as follows:
Note: Data types in shared memory cannot use containers, only basic data types can be used.
This function is used to connect shared memory to the address space of the current process.
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmget()
The shared memory identifier returned by the function.Returns the shared memory start address when the call succeeds, and returns (void *)-1
。
This function is used to separate the shared memory from the current process, which is equivalent to shmat()
The inverse of a function.
int shmdt(const void *shmaddr);
shmat()
The address to which the function returns.The call returns 0 if successful and -1 if failed.
This function is used to operate shared memory. The most common operation is to delete shared memory.
int shmctl(int shmid, int command, struct shmid_ds *buf);
shmget()
The shared memory id returned by the function.IPC_RMID
。The call returns 0 if successful and -1 if failed.
Note that using root
The created shared memory cannot be deleted by ordinary users regardless of the creation permissions.
The call returns 0 if successful and -1 if failed.
This function is used to operate shared memory. The most common operation is to delete shared memory.
int shmctl(int shmid, int command, struct shmid_ds *buf);
shmget()
The shared memory id returned by the function.IPC_RMID
。The call returns 0 if successful and -1 if failed.
Note that using root
The created shared memory cannot be deleted by ordinary users regardless of the creation permissions.
[External link image is being transferred...(img-v6qW3XRA-1720711279572)]
[External link image is being transferred...(img-CG0tGAne-1720711279572)]