Basic concepts
Program: Executable file stored in disk file
Processes: Instances of program execution
Cmd: ps ,top
Process ID: Each process has a unique process ID identified by a non-negative integer
0 is the dispatch process, 1 is the init process, (most UNIX systems) 2 is the page daemon
/*In addition to the process ID, a process can return other identifiers using the following functions*/ #include <unistd.h> pid_t getpid(void); Return: The process that invoked the process ID pid_t getppid(void); Return: The parent process of the calling process ID uid_t getuid(void); Return: The actual user who invoked the process ID uid_t geteuid(void); Return: Valid user calling process ID gid_t getgid(void); Return: Actual group of the calling process ID gid_t getegid(void); Return: A valid group of calling processes ID
Create process
fork()
In linux, the only way to create a new process is for an existing process to call the fork() function. The newly created process is a child process, and the existing process is called the parent process.
#include <unistd.h> pid_t fork(void);
The fork() function is a system call, and when the parent process calls fork(), fork() returns two values: the parent process returns the pid of the child process, which is an integer greater than 0, and the child process returns 0.Parent and child processes continue to execute statements after fork(), and child processes inherit copies of the parent's data space, stack, and stack, but do not share storage space.copy-on-write technology: The kernel changes permissions (data segments, stacks, and stacks) to read-only, and if either parent or child process wants to modify the copy, the kernel makes only one copy of the memory in the modification area, usually a page in virtual memory.
Two uses of fork():
1. A parent process duplicates itself so that the parent and child processes execute different code snippets at the same time
2. A parent process copies itself to execute different programs
vfork()
#include <unistd.h> pid_t vfork();
The difference between vfork() and fork():
1.vfork child and parent processes share data segments, fork does not share
2.vfork's child process executes before the parent process, and the parent process does not begin execution until it calls exec or exit
Terminate process
There are five ways a process can terminate normally and three ways it can terminate abnormally
Normal termination:
1. Use return in main function
2. Call the eixt function
3. Call the _exit or _Exit function
4. The last thread of the process executes the return statement in its startup routine
5. The last thread of the process calls pthread_exit
Abnormal termination:
1. Call abort()
2. When the process receives certain signals
3. The last thread responds to the Cancel request
No matter how the process terminates, the same piece of code installed by the kernel is executed.This code closes all descriptors of the process and releases its memory
If the parent process terminates before the child process ends, the child process becomes an orphan and init becomes the adoptive parent of the process
A process that has been terminated but the parent process has not been untreated becomes a zombie, ps state Z
atexit
#include <stdlib.h> int atexit(void (*func)(void));
Atexit is an exit process registration function.Exit executes atexit-registered functions first, and executes them several times, then executes them later.
Exit and_exit
The difference is that exit first performs some cleanup (such as flushing I/O) and then returns to the kernel, while _exit and _Exit return directly to the kernel
wait and waitpid
#include <unistd.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options);
Both wait and waitpid are blocked functions, but waitpid can be set to non-blocking and option to WNOHANG
Family of exec functions
#include <unistd.h> extern char **environ; 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[]); //Examples: execlp("/bin/echo", "echo", "hello", (char *)0)
system()
#include <stdlib.h> int system(const char *cmdsting);
system can execute a command in a program
Process Accounting
Process accounting is created and written when processes are created and terminated, so processes that are executing all the time do not have process accounting files, such as init processes
Process Scheduling
Processes can modify priority by changing the nice value, the higher the nice value, the lower the priority
#include <unistd.h> #include <sys/resource.h> int nice(int nice); int getpriority(int which, id_t who); int setpriority(int which, id_t who, int value);
nice values are based on 0~2*NZERO-1,
NZERO is available through sysconf (_SC_NZERO)
nice() can return -1, so Return-1 cannot determine failure, and you need to check if errno is not zero at the same time
Process Time
#include <sys/times.h> #include <sys/resource.h> struct rusage { struct timeval ru_utime; /* user CPU time used */ struct timeval ru_stime; /* system CPU time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims (soft page faults) */ long ru_majflt; /* page faults (hard page faults) */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* IPC messages sent */ long ru_msgrcv; /* IPC messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary context switches */ }; clock_t times(struct tms *buf); int getrusage(int who, strcut rusage*rusage);