“This is the 15th day of my participation in the August Gwen Challenge.
process
- Task: Target results
- Program: is a piece of code written to complete a task, is a static.
Concept of process
A process is a process performed by a program to complete a task. It is dynamic (the entire process of dynamic creation, scheduling, execution, and extinction). Processes are known as the minimum unit of resource allocation, because each process claims a virtual space of 0-4g at its initial startup.
This space is divided into two parts, 0-3G user space, 3-4G kernel space, and 0-3G unique space between processes. Each other. 3-4G is a space shared by multiple processes (later used for communication between processes). The user space of processes is independent of each other, so it has high security. A PCB process control block is also applied as a structure. Task_struct contains all of the processes’ resources
Such as PC program counters, stacks, file descriptors, process status, process numbers, and so on
Three processes are automatically created when the OPERATING system starts:
- 0: responsible for booting the system, also creates a process 1 — init process
- 1: initializes hardware and reclaims resources
- 2: Responsible for resource allocation and system scheduling
There is a race between processes. Execution speed is not guaranteed, so is the speed at which the parent-child process will end. Consider single-core and multicore cpus here.
Process scheduling mechanism
Time slice polling, context switching
Process status
Process markers
Process NUMBER (PID) : Specifies the number of processes assigned by Linux. Each process is unique and easy to manage.
When a process terminates, ownership of the process number is released. Other processes wait for it to release some time later
Distribution, not immediately after the end of the distribution.
Process-related commands
1.pstree— Displays all processes in a tree
The process number is displayed if the -p argument is added
linux@ubuntu:~/test/test04$PSTREE Systemd ─┬─ModemManager─ 2*[{ModemManager}] ├─NetworkManager─┬─ dhClient │ └ ─ 2 * [{NetworkManager}] ├ ─ VGAuthService ├ ─ accounts - the daemon ─ ─ ─ 2 * / daemon} {accounts -Copy the code
@ ubuntu Linux: ~ / test/test04 $pstree - p systemd (1) ─ ┬ ─ ModemManager (804) ─ ┬ ─ {ModemManager} (846) │ └ ─ {ModemManager} (854). ├ ─ NetworkManager (852) ─ ┬ ─ dhclient (958) │ ├ ─ {NetworkManager} (912) │ └ ─ {NetworkManager} (916) ├ ─ VGAuthService (1283). ├ ─ accounts - the daemon (812) ─ ┬ ─ daemon} {accounts - (826) │ └ ─ daemon} {accounts - (830).Copy the code
2.ps -ef– Displays the relationship between the parent and child processes
linux@ubuntu:~/test/test04$ ps -ef
UID PID PPID C STIME TTY TIME CMD
linux 2214 1581 0 09:07 ? 00:00:50 /usr/lib/gnome-terminal/
linux 2220 2214 0 09:07 pts/0 00:00:00 bash
linux 2317 2214 0 09:28 pts/1 00:00:00 bash
linux 2332 2317 0 09:30 pts/1 00:00:00 vi test.c
Copy the code
PID Process ID PPID ID of the parent process
3.ps aux– Check the process status
linux@ubuntu:~/test/test04$ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.2 159996 9328? Ss 09:01 0:04 /sbin/in root 2 0.0 0.0 0? S 09:01 0:00 [rcu_gp] S 09:01 0:00 [rcu_gp]Copy the code
Process status:
R | Running state |
S | A dormant state |
I(capital I) | The idle state |
T | Stop state |
Z | The zombie state |
< | High priority process |
N | Low priority |
L (lowercase l) | This process contains threads |
+ | Foreground process |
s | Session header process |
4.ps -ajx— Focus on family relationships
linux@ubuntu:~/test/test04$ ps -ajx PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 0 1 1 1 ? -1 Ss 0 0:04 /sbin/init a 0 2 0 0 ? -1 S 0 0:00 [kthreadd] . . . 2214 2220 2220 2220 pts/0 3812 Ss 1000 0:00 bash 2214 2317 2317 2317 pts/1 2332 Ss 1000 0:00 bash 2317 2332 2332 2317 pts/1 2332 S+ 1000 0:00 vi test.c 2 3637 0 0 ? -1 I 0 0:11 [kworker/0:1 2 3666 0 0 ? -1 I 0 0:00 [kworker/u25 2 3740 0 0 ? -1 I 0 0:00 [kworker/u25 2 3808 0 0 ? -1 I 0 0:00 [kworker/u25 2220 3812 3812 2220 pts/0 3812 R+ 1000 0:00 ps -ajxCopy the code
PGID: indicates the ID of a process group
SID: indicates the session ID
The session
A session is a collection of one or more processes to complete a task. There are three main parts to a conversation
- First session process: the process that creates the session
- Foreground process group: A collection of related foreground processes
- Multiple background process groups: A collection of processes that may not be related
📢 Note: The first session process manages the entire session. If the first session process ends, all processes in the session end
5.top– the CPU share
Dynamically viewing process information: Displays the CPU usage of a process
linux@ubuntu:~/test/test04$top top - 19:27:56 up 10:26, 1 User, Load Average: 0.02, 0.03, 0.00 327 total, 1 running, 258 sleeping, 0 stopped, 0 zombie %Cpu(s): 4.5US, 3.1SY, 0.0Ni, 92.5ID, 0.0wa, 0.0hi, 0.0Si, 0.0st KiB Mem: 4001668 total, 1796372 free, 1312536 used, 892760 buff/cache KiB Swap: 2097148 total, 2097148 free, 0 Use.2441892 Avail Mem process USER PR NI VIRT RES SHR � %CPU % Mem TIME+ COMMAND 1601 Linux 20 0 393132 56328 32848 S 3.0 1.4 1:05.81 Xorg 1726 Linux 20 0 3056316 205076 95484s 3.0 5.1 1:37.78 GNOMe-shell 2214 Linux 20 0 796560 57740 43144s Gnome-termin + 3822 Linux 20 0 51364 4156 3380 R 1.0 0.1 0:00.31 Top 1204 root 20 0 194612 13644 11120 S 0.3 0.3 0:56. 93 vmtoolsdCopy the code
6.jobsView the user daemon process list
- CTRL + Z: Pauses a foreground process and saves it in the background
- Fg: The process suspended in the background is restored to the foreground
- Fg + % sequence number: Restores the specified background pause program to the foreground
- Bg: The background pause program will run in the background
- Bg + % Sequence number: Specifies which process
- Executable program name + & : Runs the process in the background
Create process: fork
-
#include
#include
-
Prototype: pid_t fork(void);
-
Function: Create a child process
-
Parameters: no
-
The return value:
Success: 📌 returns the ID number of the child process to the parent process and 0 to the child process
Returns -1 on failure;
📢fork: There is only one condition for failure, running out of memory.
-
Code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, const char *argv[])
{
int fd = open("./1.txt",O_RDWR|O_CREAT,0666);
if (- 1 ==fd)
{
perror("open");
return - 1;
}
// Create a child process
pid_t pid = fork();// create a child process
if(- 1 == pid)
{
perror("fork");
return - 1;
}
// Use the return value mechanism to make parent and child processes do different things separately
if(pid == 0)
{
/ / the child process
printf("I am child process \n");
write(fd,"hello world".11);
}
else if(pid > 0) {/ / the parent process
char buf[123] = {0};
sleep(1);
close(fd);
fd = open("./1.txt",O_RDONLY);
printf("I am the parent process, and the ID of my child process is %d\n",pid);
read(fd,buf,sizeof(buf));
printf("buf = %s\n",buf);
}
while(1);
return 0;
}
Copy the code
linux@ubuntu:~/test/test04$./a.out I am the child process I am the parent process. The ID of my child process is 3866 buf = hello world!Copy the code
When the fork!
Note that the second linux@ubuntu:~/test/test04$, the Linux mechanism stipulates that as a child process, it must let the parent process collect for it. When the parent process is running, the bash parser is a little later than the parent process, because the bash parser is the parent process and waits for the parent process to finish and reclaim it.
1. The pit
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
printf("hello");
fork();
printf("world");
return 0;
}
Printf does not print '\n'. Hello is still in the cache. The child will copy this along with it.
linux@ubuntu:~/test/test04$ ./a.out
helloworldlinux@ubuntu:~/test/test04$ helloworld
Copy the code
2. Add ‘\ n’
int main(int argc, const char *argv[])
{
printf("hello\n");// add '\n '
fork();
printf("world");
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello
worldlinux@ubuntu:~/test/test04$ world
Copy the code
3. More than one fork
int main(int argc, const char *argv[])
{
fork();
fork();
printf("hello\n");
printf("world");
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello
worldlinux@ubuntu:~/test/test04$ hello
worldhello
worldhello
world
Copy the code
int main(int argc, const char *argv[])
{
int i;
for(i=0; i<3; i++) {printf("hello world\n");
fork();// Put it underneath
}
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello world
hello world
hello world
linux@ubuntu:~/test/test04$ hello world
hello world
hello world
hello world
Copy the code
int main(int argc, const char *argv[])
{
int i;
for(i=0; i<3; i++) { fork();// Put it on top
printf("hello world\n");
}
return 0;
}
linux@ubuntu:~/test/test04$ ./a.out
hello world
hello world
hello world
linux@ubuntu:~/test/test04$ hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
Copy the code
4. Check the father-child relationship
int main(int argc, const char *argv[])
{
printf("hello\n");
fork();
printf("world");
while(1);
return 0;
}
Copy the code
Open another terminal
linux@ubuntu:~$ ps aux
linux 4070 48.2 0.0 4504 744 pts/0 R+ 19:59 0:03 ./a.out
linux 4071 48.2 0.0 4504 80 pts/0 R+ 19:59 0:03 ./a.out
Copy the code
linux@ubuntu:~$ ps -ef
linux 4083 2220 46 20:02 pts/0 00:00:05 ./a.out
linux 4084 4083 46 20:02 pts/0 00:00:05 ./a.out
Copy the code
copy-on-write
The fork function creates the child process by copying the parent process’s resources, but the child process does not have to use the resources, so the child process shares the parent process’s resources first. If either of the parties modifies the content, copy a copy to the child process before modifying it. This is called copy-on-write technology.
File sharing
If some files are opened between forks, some file descriptors are obtained. The parent and child processes share the file descriptors obtained before the fork. Then in the process of operation, it is possible to cause read and write Pointers to affect each other.
Copy files using a process
📝 Exercise: Use two processes to copy a file, copying one file to another
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
// Use file IO to open the file and get the file size
int fd = open(argv[1],O_RDONLY);
if (- 1 == fd)
{
perror("open");
return - 1;
}
int fd1 = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666);
if (- 1 == fd1 )
{
perror("open1");
return - 1;
}
// Get the file size using the offset
int len = lseek(fd,0,SEEK_END);
// You need one from the beginning and one from the middle. You need to find the middle
len = len / 2;
// Start creating the child process
// The child reads from the middle and writes from the middle
// The parent process reads from the beginning, writes from the beginning, and finishes in the middle
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if (pid == 0 )
{
// Subprocess -- middle
close(fd);// Avoid affecting the parent process's read/write pointer
close(fd1);
fd = open(argv[1],O_RDONLY);
if (- 1 == fd)
{
perror("open");
return - 1;
}
fd1 = open(argv[2],O_WRONLY);
if( - 1 == fd1)
{
perror("open1");
return - 1;
}
// Offset the read/write pointer to the file being read to the middle
lseek(fd,len,SEEK_SET);
// Offset the read/write pointer of the file being written to the middle
lseek(fd1,len,SEEK_SET);
char buf[123] = {0};// Receive read input, used when writing data
ssize_t ret = 0;// take over the return value of read
while((ret = read(fd,buf,123)))
{
if( - 1 == write(fd1,buf,ret))
{
perror("write");
return - 1;
}
}
close(fd);
close(fd1);
exit(0);
}else if (pid > 0)
{
// Parent process -- start
lseek(fd,0,SEEK_SET);
lseek(fd1,0,SEEK_SET);
char buf[123] = {0};
ssize_t ret = 0;
while(len)// Subtract what you have read each time using the workload as a loop condition
{
if (len >= 123)
{
ret = read(fd,buf,123);
}else{ ret = read(fd,buf,len); } write(fd1,buf,ret); len = len - ret; }}Copy the code
Gets the process ID interface
Getpid:
-
Run the following command to obtain the ID of its own process
-
The header file:
#include <sys/types.h>
#include <unistd.h>
-
Pid_t getPID (void)
-
Parameters: no
-
The return value:
Successfully returns its own process ID
There is no failure
Getppid:
-
Run the following command to obtain the process ID of the parent process
-
Pid_t getppID (void);
-
Parameters: no
-
The return value:
Returns the ID number of its parent process
There is no failure
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if ( 0 == pid)
{
printf("I am child process \n");
printf("I'm a child process and my process number is %d\n",getpid());
printf("I am the child process and my parent process is %d\n",getppid());
}else if(pid > 0 )
{
printf("I am the parent process \n");
printf("I am the parent process, and the ID of my child process is %d\n",pid);
sleep(1);
printf("I am the parent process, my process ID is %d\n",getpid());
printf("I am the parent process, my parent process ID is %d\n",getppid()); }}Copy the code
Three functions to terminate a process
Exit:
- The header file:
#include <stdlib.h>
- Prototype:
void exit(int status);
- Function: To end a process, release the buffer first
- Parameter: status: Indicates the status of ending a process. It is the same as return
- Returned value: None
_exit:
- #include
- Void _exit(int status);
- Function: Terminates a process without releasing the buffer
- Parameter: status: Indicates the status of ending a process. It is the same as return
- Returned value: None
atexit:
-
#include
-
Int atexit(void (*function)(void));
-
// Call function when the process is finished
-
Argument: a function pointer to void when the return value is a parameter of type void
-
The return value:
Returns 0 on success
Failure returns a non-zero value
Code:
#include <stdio.h>
#include <stdlib.h>
// Prepare a void fun(void) function
void fun(void)
{
printf("hello wrold\n");
}
int main(int argc, const char *argv[])
{
// Start registering the function
atexit(fun);
sleep(3);
return 0;
}
Copy the code
Orphan Process:
The parent process terminates before the child process. If a child loses its parent, the child considers process 1 as its parent. Process 1 is responsible for collecting and managing child processes. Let’s say that many child processes consider process 1 to be their parent. Process 1 can be very heavy, so we try to write the code so that the parent reclaims the child’s resources before it finishes. Orphan process is harmless.
Zombie progression:
The child process terminates before the parent process. The child process assumes that the parent will reclaim its resources. But the parent has been busy doing its own thing and has not reclaimed the child, so the child can’t be reclaimed, but the child is finished. So the child process becomes zombie. Zombie processes are dangerous.
📢 Note: In the future, child process resources need to be reclaimed whenever a fork is written.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if(pid == 0)
{
exit(0);// The child process is terminated. The parent process is not terminated, and the child process becomes a zombie process
}else if(pid > 0 )
{
while(1){
sleep(1); }}return 0;
}
Copy the code
Handling zombie processes:
Wait:
-
The header file:
#include <sys/types.h>
#include <sys/wait.h>
-
Prototype: pid_t wait(int *wstatus);
-
Function: block waiting to reclaim any child process resources
-
Parameter: wSTATUS: indicates the end status of the process. The default mode is NULL, regardless of the end status of the process. If you want to receive the status value returned by exit, it will place the status value returned by exit into the 8-15 bits of the wSTATUS address.
linux@ubuntu:~/test/IO/test$ ./a.out 0x7ffd5b0d5090 linux@ubuntu:~/test/IO/test$ ./a.out 0x7ffeb92b3760 linux@ubuntu:~/test/IO/test$ ./a.out 0x7ffdb51c1c20 0x0000000 Copy the code
-
The return value:
Success returns the ID number of the received process
Failure returns -1;
-
Note: If the parent process calls WAIT to reclaim resources, it blocks the wait. Reduces the efficiency of the parent process.
-
Code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if(pid == 0)
{
sleep(5);
exit(0);// The child process is terminated. The parent process is not terminated, and the child process becomes a zombie process
}else if(pid > 0 )
{
// In the parent process
printf("Parent process running \n");
printf("Accepted successfully, received child process ID %d\n",wait(NULL));
}
return 0;
}
Copy the code
Waitpid:
-
The header file:
#include <sys/types.h>
#include <sys/wait.h>
-
Pid_t waitPID (pid_t pid, int * wSTATUS, int options);
-
Function: Parameter:
-
The return value:
Successfully returns the ID number of the reclaimed child process
Returns -1 on failure;
-
If: WNOHANG returns 0 if the child process is not finished
The most common use is waitpid(-1; NULL; WNOHANG);
-
Note: you need to call the function frequently to see if the child process is finished
-
Code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include<stdlib.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if(pid == 0) / / the child process
{
sleep(5);
exit(0);// The child process is terminated. The parent process is not terminated, and the child process becomes a zombie process
}else if(pid > 0 )/ / the parent process
{
pid_t pid1 = 0;
while(1)
{
printf("The parent is minding its own business \n");
if( 0 < (pid1 = waitpid(- 1.NULL,WNOHANG)))
{
printf("Reclaimed child process resource, child process ID %d\n",pid1);
}
sleep(1); }}return 0;
}
Copy the code
daemon
It’s a special process mechanism, a process that silently serves my work. Is a background process. The init process is a daemon. Background process: only writes data to the terminal, but does not read data to the terminal. If terminal input is retrieved, the background process is terminated immediately. You want to get out of terminal management, out of session management. Daemons are used for example, server, HTTP, TFTP, FTP
Add-on: CTRL + C sends a kill signal to all foreground processes (if the parent process terminates and the child process is orphaned by process 1, then CTRL + C has nothing to do with the child process)
Creating daemons has a set of steps
-
The orphaned process. () kill: sends a signal to the process
-
Create a new session that becomes the session lead process setsid
#include
#include
Prototype: pid_t setsid(void);
Function: Creates a new session, and the creator calls the first process of the session
Parameters: no
Return value: A new session ID is returned on success. -1 is returned on failure
-
Example Modify the default working directory file chdir
#include <unistd.h>
Int chdir(const char *path);
Run the following command to modify a working path
Return value: 0 is returned on success, -1 is returned on failure
-
Give the highest file permission umask
#include <sys/types.h> #include <sys/stat.h>
Prototype: mode_t umask(mode_t mask);
Parameter: the value of the mask you want to modify
Return value: The modified mask value must be returned successfully
-
Close the file descriptor close (0) (0 represents terminal); Note if no operation is performed on the terminal, close all file descriptors
-
Start doing daemon events such as writing to log files
-
Additional: getdtablesize
Function: Count the number of file descriptors for the process
#include <unistd.h>
Int getDtablesize (void);
Parameters: no
Return value: The number of file descriptors successfully returned
-
Code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
// Create an orphan process
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if(0 == pid)
{
/ / the child process
// Create a session and become your own master
if(- 1 ==setsid())
{
perror("setsid");
return - 1;
}
// Modify the working directory
if(- 1 == chdir("/"))
{
perror("chdir");
return - 1;
}
// Change the file mask
umask(0);
// Close the file descriptor
close(0);
close(1);
close(2);
FILE * fp = fopen("./1.txt"."a");
while(1)
{
// Write a log file
fprintf(fp,"Hello world\n");
fflush(fp);
sleep(1); }}// If the parent process is left alone, the parent process terminates automatically
return 0;
}
Copy the code
The EXEC family
Some set of functions. In this set of processes, all functions perform a function, but the use of the function is different. The function is as follows: Replace this process with another process to avoid space re-release and space requisition
System: Function: Calls other processes in a process
execl
-
Int execl(const char *path, const char *arg,… /* (char *) NULL */);
-
Parameters:
Path: indicates the path of the executable file
Arg: parameter passed to the executable
Can be multiple arguments: Fixed rules: “Name of executable file”, “parameter 1″,” parameter 2″.. End, NULL
-
The return value:
If the execution succeeds, no return is made
Returns -1 on failure
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if(0 == pid)
{
printf("Child process doing its own thing \n");
sleep(3);
printf("Child process task terminated \n");
// Replace other processes to continue using the space --ls
if(execl("/bin/ls"."ls"."-l".NULL) = =- 1)
{
perror("execl");
return - 1;
}
printf("Child process doing its own thing \n");
// This statement will not print because the child process has been replaced
}
else if(pid > 0)
{
//wait
wait(NULL);
}
return 0;
}
Copy the code
linux@ubuntu:~/demo/test/IO/test$./a.out Subprocess doing its own thing Subprocess task End Total number 655728 - RWXRWXRWX 1 Linux Linux 671444992 August 26 17:47 TXT -rwxr-xr-x 1 Linux Linux 8512 8月 27 07:44 a. ut -rwxrwxrwx 1 Linux Linux 724 8月 27 07:44 test.cCopy the code
execlp
-
Int execlp(const char *file, const char *arg,… /* (char *) NULL */);
-
Functional differences: Only executable files in the PATH environment variable can be called
-
Parameters:
File: indicates the name of the executable file
Arg: parameter passed to the executable
Can be multiple arguments: Fixed rules: “Name of executable file”, “parameter 1″,” parameter 2″.. End, NULL
-
The return value:
If the execution succeeds, no return is made
Returns -1 on failure
-
code
execv
-
Execv (const char *path, char *const argv[]);
-
Parameters:
Path: indicates the path name of the destination
Arg: parameter passed to the executable
Can be multiple arguments: Fixed rule: {” name of executable “, “parameter 1″,” parameter 2″, NULL} end
-
The return value:
If the execution succeeds, no return is made
Returns -1 on failure
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if(- 1 == pid)
{
perror("fork");
return - 1;
}
if(0 == pid)
{
printf("Child process doing its own thing \n");
sleep(3);
printf("Child process task terminated \n");
// Replace other processes to continue using the space --ls
/* if(execl("/bin/ls","ls","-l",NULL) == -1)//execl { perror("execl"); return -1; } * /
/*if(execlp("ls","ls","-l",NULL) == -1)//execlp { perror("execlp"); return -1; }* char * arg[] ={"ls","-l",NULL} ; //execv if(execv("/bin/ls",arg) == -1) { perror("execl"); return -1; } printf(" child process doing its own thing \n"); } else if(pid > 0) {//wait wait(NULL); } return 0; }Copy the code