Introduction: in this section, we will explain the concepts related to process control. We’ll cover process identifiers, process creation, recycling, and some process-related functions.
1: First, let’s introduce the concept of process.
A: Process identifiers: The process identifiers we are talking about here are process IDS. We introduced process valid user ids and valid group ids earlier. Process IDS will be explained in more detail here. 1> : First point: on a machine, each process has a unique process ID, which is used to distinguish different processes. We usually call the process ID as the process identifier. We can get pid_t getpid() using the following function; This function returns the process ID of the calling process, and it is important to note that the process ID is stored using the pid_t structure. In Linux, keywords that end in _t are usually redefined using typedef. In Linux, there are many background processes running. Usually, the process with ID 0 is the initialized process. There are other processes that we will not cover here. We can also get the ID of the parent process using the following process, pid_t getppID (); This function returns the ID of the parent of the calling process. Let's look at the valid user ID and group ID of the process and the actual user ID and group ID of the process: Normally, the process valid ID and the actual ID are the actual ids of the calling process user, but if we set the program file to the keywords described in the previous section, the process valid user ID is the program file valid ID. The valid ID of the process determines the process's access to the file. Just like the passwd file, it sets that key, so each of us can change the user password. Next, we show how to change the process-related ID functions. First, we show you how to change a valid user ID for a process. int seteuid(uid_t uid); int setegid(gid_t gid); These two functions set the user's valid user ID and the actual user ID bit, but there are some setting conditions. When the program is a superuser, the program can set the valid user ID bit parameter UID. If the program is not a superuser, you can only set the valid user ID to the actual user ID of the program or save the Settings. Other cases cannot be set and an error will occur. int setuid(uid_t uid); int setgid(gid_t gid); This function is somewhat similar to the one above, but it can change all the ID bits. When the executing process has superuser privileges, it can set the actual ID, the valid ID, and the ID of the saved Settings to the ID of the parameter. If there is no privilege, the result is the same as above. Other cases will fail. Int setreuid (uid_t ruid, uid_t euid); Int setregid(gid_t rgid, gid_t egid): If an unprivileged user uses this function, the actual user ID and the valid user ID are exchanged. If it is a superuser, set the actual user ID and the valid user ID to the corresponding ID of the parameter (if the corresponding parameter is -1, the corresponding ID will remain unchanged). ! [file](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/689e47f7e17f41b389deacf8c87cce75~tplv-k3u1fbpfcp-zoom-1.image)Copy the code
2: Next, we’ll look at process-related identifiers and some process-related functions.
Each process has a unique process ID identified by a non-negative integer. This ID is uniquely deterministic for a system. A: Process creation. pid_t fork(); // This function is used to create the process and its return value is the ID of the process created. But this function is called once, but it returns twice, in the parent it returns the ID of the created child, and in the child it returns 0. The child and parent processes continue to execute the commands following the fork. The child is a copy of the parent (the parent only shares the body segment) and is copy-on-write and read-on-share for things like heaps and stacks. One thing to note here, however, is that the order in which the child and parent execute is uncertain. Of course, the child also inherits a lot of content from the parent, as shown in the following figure for the file descriptor opened by the parent.Copy the code
The process also inherits the following resources.Copy the code
At the same time, the fork function may fail. Each user with an actual ID has a limit on the number of processes. When we exceed this limit, we cannot create new processes. pid_t vfork(); The vfork function also creates a process. The difference, however, is that it doesn't fork. It will only run in the address space of the parent process and will continue to run when the process created by vfork exits. And the purpose of using this function is to exec a new program. Wait and waitPID functions: These two functions are used to reclaim the child process. When our child terminates, the kernel sends a SIGCHLD signal to the parent process. Since child termination is an asynchronous event, it sends a signal process notification. The parent process can choose to ignore or call a particular function. Pid_t wait(int *statloc); pid_t waitpid(pid_t pid, int *statloc, int ptions); Statloc: This parameter records the return status. WIFEXITED(status) is not 0 → The process ends normally. WEXITSTATUS(status) The previous macro is true. Wait signaled (Status) from the signaled signaled (signaled) that the process will end. 2. Wait signaled (Status) from the signaled signaled (signaled) that the process will end. WSTOPSIG(status) If the above macro is true, use this macro → Get the number of the signal that causes the process to pause. WIFCONTINUED(status) is true → The process continues after being paused pid Indicates the name pid and the type pid_t. But when the PID takes a different value, it has a different meaning here. When pid>0, waitPID waits only for the child whose process ID is PID. No matter how many other child processes have finished running and quit, waitPID waits until the specified child process has finished. When pid=-1, wait for any of the child processes to exit without any restrictions, and waitPID is the same as wait. When pid=0, waitPID waits for any child process in the same process group. If the child process has already joined another process group, waitPID does not do anything about it. When pid<-1, wait for any child processes in a specified process group whose ID is equal to the absolute value of the PID. Options provides some additional options to control waitpid, currently in Linux support WNOHANG and WUNTRACED only two options, these are two constants, can use "|" connected operators use WNOHANG: If there are no finished child processes, return immediately without waiting. WUNTRACED: If a child process enters a suspended execution, it returns immediately but is not in the end state. WCONTINUED: I'm not sure what that macro means. int waitid(idtype_t idtype, id_t id, siginfo_t *iinfop, int options); Similar to waitPID, the waitid function allows a process to specify which child process to wait on. But it uses a separate parameter to identify the type of child process to wait on. P_PID: waits for a specific child process. The id parameter is the child process to wait for. P_PGID: waits for any child process in a process group. Id is the process group ID. P_ALL: waits for any child process. Options: WCONTINUED: waits for a process that was previously suspended but continues, and its status is not reported. WEXITED: waits for an exited process. WNOHANG: If no child process is available to exit, return immediately and block. WNOWAIT: Does not break the state of the child process. The exit state of the child process can be obtained by the previous function call. WSTOPPED: Waiting for a child process that has been paused but whose status has not been reported. Infop: This keyword contains detailed information about generated signals for process state changes. pid_t wait3(int *statloc, int optinos, struct rusage *rusage); pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage); These two functions are not covered here.Copy the code
Finally, we’ll cover some process-related functions.
int system(const char* cmdstring); This function is used to execute the command corresponding to the cmdString string, and returns a non-zero value when the cmdString string is empty and the system program is available. FILE* popen(const char* command, const char* type); This function executes command and returns a pointer to the FILE descriptor, where type is read or write to the FILE descriptor. int pclose(FILE *stream); Use this function to close the previously returned file descriptor,Copy the code