Summary of 15th days of study during winter vacation (linux advanced programming)
Then yesterday
1. process 2. Create a process
(1) int system (const char * command );
(2) FILE * popen (const char * command, const char * type );
(3)Exec Functions
Int execl (const char * path, const char * arg ,...);
// The first parameter: The replaced process, and the second parameter... command line
// Command line format: command name option parameter. The command line must end with 0.
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 []);
Replace the code data of the code space of the current process. The function will not create a process. See example 1.
Differences between execl and execlp
Execl must be an absolute path. execlp is not used in example 2.
Example 1:
Test. c
#include <stdio.h>#include <unistd.h>int main(int argc, const char *argv[]){ printf("%d\n",getpid()); sleep(5); return 0;}
# Include <stdio. h> # include <unistd. h> int main (int argc, const char * argv []) {printf ("% d \ n", getpid (); int r = execl ("test ", "mytest", NULL); // the end must be 0 printf ("end % d \ n", r); return 0 ;}
Printf ("end % d \ n", r) during running; not executed
And the printed two PIDs are the same.
Example 2:
#include <stdio.h>#include <unistd.h>int main(int argc, const char *argv[]){ printf("%d\n",getpid()); int r=execl("/bin/ls","ls","-l",NULL); printf("end %d\n",r); return 0;}
(4) pid_t fork (void );
1. Clone the code and execution location of the parent process, and start the re-fork process in two processes. Example 1
2. The Parent and Child processes created by fork are simultaneously executed.
After the child process is created, the parent process immediately submits the time slice to the system, and the system executes the time slice during the next scheduling. Example 2
Example 1:
# Include <stdio. h> # include <unistd. h> int main (int argc, const char * argv []) {printf ("before creat process! \ N "); int pid = fork (); printf (" after creat process: % d \ n ", pid); return 0 ;}result: before creat process! After creat process: 2651 after creat process: 0 // Why is it 0? Because fork not only clones the code of the parent process but also the execution location of the parent process, pid = fork () is not executed in the child process, and pid is 0.
Example 2:
# Include <stdio. h> # include <unistd. h> int main (int argc, const char * argv []) {printf ("before creat process! \ N "); int pid = fork (); while (1) {if (pid = 0) {printf (" AAAAA \ n "); sleep (1 );} else {printf ("BBBBB \ n"); sleep (1) ;}}return 0 ;}result: The AAAAA and BBBBB are displayed.
3. Process application
1. What is the use of fork? Use fork to implement multi-task (Unix itself does not support multithreading, and sometimes it is necessary to use fork to create multi-process)
2. Multi-task implementation
1. Thread
2. Process
3. Signal
4. asynchronous
5. Process pool and thread pool
Example: Use a process to create multiple tasks (display the time and random number on the screen at the same time)
# Include <curses. h> # include <unistd. h> # include <stdlib. h> # include <time. h> WINDOW * wtime, * wnumb; int main (int argc, const char * argv []) {initscr (); box (stdscr, 0, 0); wtime = derwin (stdscr,, 0, (COLS-10); // the upper right corner shows the time wnumb = derwin (stdscr, (LINES-3)/2, (COLS-11) /2); // the random number box (wtime,); box (wnumb,); refresh (); wrefresh (wtime); wrefresh (wnumb ); if (fork () {// parent process time_t tt; struct tm * t; while (1) {tt = time (0); t = localtime (& tt ); mvwprintw (wtime, 1,1, "% 02d: % 02d: % 02d", t-> tm_hour, t-> tm_min, t-> tm_sec); refresh (); wrefresh (wtime); wrefresh (wnumb); sleep (1) ;}} else {// sub-process while (1) {mvwprintw (wnumb, 1, 1, 1, "% 8d ", rand () % 100000000); refresh (); wrefresh (wtime); wrefresh (wnumb); usleep (100000) ;}} endwin (); return 0 ;}
4. Understanding processes (1). Relationship between parent and child Processes
Two independent processes with their own pid
The process tree shows two independent but not parallel parent-child nodes (pstree can view the process tree)
(2) parent process ended first
The sub-process depends on the Root process init (orphan process)
Theoretically, the orphan process has no harm to the system.
Child process ended first
Sub-processes become zombie processes.
Zombie processes do not occupy memory, but the CPU occupies a node in our process task management tree.
Botnets can cause a waste of process quota resources.
(3). Zombie process recycling (using wait for recycling)
Example:
#include <stdio.h>#include <stdlib.h>#include <sys/wait.h>int main(int argc, const char *argv[]){ if(fork()){ int status; printf("parent\n"); wait(&status); printf("%d\n",WEXITSTATUS(status)); sleep(1000); }else{ printf("child\n"); sleep(10); exit(34); } return 0;}After 10 seconds of running, the sub-process will be recycled and will not become a zombie process. pstree cannot see the sub-process.
4. How does the parent process know that the child process exits?
When a child process ends, it usually sends a SIGCHLD signal to the parent process (kill-l can view all signals)
5. The parent process processes the exit signal of the child process.
Signal (int sig, void (* fun) (int ));
Register with the system: Tell the system to stop the process as long as the sig signal occurs and call the fun function.
When the function execution is complete, continue the original process (interrupted)
1. Implement processing functions
2. Use signal to bind signals and functions
Example: Zombie process recycling
# Include <stdio. h> # include <stdlib. h> # include <sys/wait. h> void deal (int s) {int status; wait (& status); printf ("recycling !... \ N "); // This function will not run sleep (10) without execution completion of the program; printf (" recycled: % d \ n ", WEXITSTATUS (status);} int main (int argc, const char * argv []) {if (fork () {signal (17, deal ); // register SIGCHLD with the system: 17 while (1) {printf ("parent \ n"); sleep (1) ;}} else {printf ("child \ n "); sleep (10); printf ("child out \ n"); exit (34);} return 0 ;}
6. Resource Access for parent and child processes (1). Memory resource 1
# Include <stdio. h> # include <unistd. h> int main (int argc, const char * argv []) {int a = 20; if (fork () {printf ("patent a: % d \ n ", a); printf ("patent a: % p \ n", & a); a = 33; sleep (3) ;}else {printf ("child: % d \ n ", a); printf (" child a: % p \ n ", & a); sleep (2); printf (" child: % d \ n ", a); printf (" child a: % p \ n ", & a);} return 0 ;}result: patent a: 20 patent: 0x7fffbd3e533cchild a: 20 child a: 0x7fffbd3e533cchild a: 20 child a: 0x7fffbd3e533c
# Include <stdio. h> # include <unistd. h> int main (int argc, const char * argv []) {int * a = (int *) malloc (4); * a = 20; if (fork ()) {printf ("patent a: % d \ n", * a); printf ("patent a: % p \ n", a); a = 33; sleep (3);} else {printf ("child a: % d \ n", * a); printf ("child a: % p \ n", ); sleep (2); printf ("child a: % d \ n", * a); printf ("child a: % p \ n", );} return 0;} result: patent a: 20 patent a: 0x1d2f010child a: 20 child a: 0x1d2f010child a: 20 child a: 0x1d2f010
The preceding two examples show that
The sub-process clones the entire memory area, but the memory area points to different physical spaces (the virtual address is the same, but the ing is different)
Despite cloning, the memory is independent and cannot be accessed from each other.
Multi-Process multi-task implementation, data exchange between processes is a big problem Inter-Process Commucation
2
# Include <stdio. h> # include <unistd. h> # include <sys/mman. h> int main (int argc, const char * argv []) {int * a = (int *) mmap (, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED ); * a = 20; if (fork () {printf ("patent a: % d \ n", * a); printf ("patent a: % p \ n ", a); * a = 33; sleep (3);} else {printf ("child a: % d \ n", * a); printf ("child: % p \ n ", a); sleep (2); printf (" child a: % d \ n ", * a); printf (" child: % p \ n ", a) ;}return 0 ;}result: patent a: 20 patent a: 0x7f76f73f1000child a: 20 child a: 0x7f76f73f1000child a: 33 // changed, child a: 0x7f76f73f1000
# Include <stdio. h> # include <unistd. h> # include <sys/mman. h> int main (int argc, const char * argv []) {// the difference with the preceding example is that you change PROT_SHARE to MAP_PRIVATE int * a = (int *) mmap, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); * a = 20; if (fork () {printf ("patent a: % d \ n", * ); printf ("patent a: % p \ n", a); * a = 33; sleep (3);} else {printf ("child a: % d \ n ", * a); printf ("child a: % p \ n", a); sleep (2); printf ("child a: % d \ n", * ); printf ("child a: % p \ n", a);} return 0;} result: patent a: 20 patent a: 0x7fe9bb8ab000child a: 20 child a: 0x7fe9bb8ab000child: 20 // child a: 0x7fe9bb8ab000 is not changed
Ing memory
MAP_SHARED: maps to the same physical memory.
MAP_PRIVATE: maps to different physical memory
# Include <stdio. h> # include <unistd. h> # include <sys/mman. h> int main (int argc, const char * argv []) {int * a = sbrk (4); * a = 20; if (fork ()) {printf ("patent a: % d \ n", * a); printf ("patent a: % p \ n", a); * a = 33; sleep (3);} else {printf ("child a: % d \ n", * a); printf ("child a: % p \ n", ); sleep (2); printf ("child a: % d \ n", * a); printf ("child a: % p \ n", );} return 0;} result: patent a: 20 patent a: 0x12a1000child a: 20 child a: 0x12a1000child a: 20 child a: 0x12a1000
Which of the following is the sbrk ing?
MAP_PRIVATE
(2). File Resources
# Include <stdio. h> # include <fcntl. h> int main (int argc, const char * argv []) {int fd = open ("test.txt", O_RDWR); if (fork ()) {printf ("patent \ n"); char buf [1024] = {0}; read (fd, buf, 1024); printf ("% s \ n ", buf);} else {printf ("child \ n"); char buf [1024] = {0}; read (fd, buf, 1024 ); printf ("% s \ n", buf);} close (fd); return 0100000000test.txt content 123456 result: patent123456child
File is independent, close (), every process must have
Why does the sub-process have no content? Because the pointer managed by the system in read is moved, the two processes operate on the same kernel object.
Change it to the following.
# Include <stdio. h> # include <fcntl. h> int main (int argc, const char * argv []) {int fd = open ("test.txt", O_RDWR); if (fork ()) {printf ("patent \ n"); char buf [1024] = {0}; lseek (fd, 0, SEEK_SET); read (fd, buf, 1024 ); printf ("% s \ n", buf);} else {printf ("child \ n"); char buf [1024] = {0}; lseek (fd, 0, SEEK_SET); read (fd, buf, 1024); printf ("% s \ n", buf) ;}close (fd); return 0 ;}result: patent123456child123456
# Include <stdio. h> # include <unistd. h> # include <fcntl. h> # include <sys/mman. h> main () {int fd = open ("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); if (fork () {write (fd, "Hello ", 5); close (fd);} else {write (fd, "Word", 5); close (fd) ;}} cat test.txt result: HelloWord
# Include <stdio. h> # include <unistd. h> # include <fcntl. h> # include <sys/mman. h> main () {if (fork () {int fd = open ("test.txt", O_RDWR); write (fd, "Hello", 5 ); close (fd) ;}else {int fd = open ("test.txt", O_RDWR); write (fd, "Word", 5); close (fd );}} cat test.txt result: Word
Conclusion:Between two processes, the file description points to the data exchange of the same file object process. There are two ways: Memory: ordered/unordered mmap file: ordered/unordered common fileIt can be concluded that the communication between all process objects is based on the kernel object.: File, memory, queue