Process control -- chlaws

Source: Internet
Author: User

Process control -- chlaws
Before the article, you need to briefly understand related functions and concepts. If you already know that you do not need to read it again, you can skip the previous section.

1. First of all, I would like to give a brief description of some functions that are subordinate to process control. If you still do not understand them, use the man command to refer to manual.
Function for obtaining process ID and parent process ID
Getpid ()/getppid ()

Obtain the actual user and valid user ID.
Note that the actual user ID indicates the user who runs the process, and the valid user ID indicates the identity of the user who runs the process.
Example: User A: a file is created, and this program is executed as root. This file has the root permission during execution.
The actual user ID is A, and the valid user ID is the root user ID.
Getuid ()/geteuid (),

Obtain the actual group ID and valid group ID
Getgid ()/getegid ()
Corresponding function with user ID and group ID set
Setuid (UID)/Setgid (GID)

Fork creates a new process (completely copying the parent process resource) // The vfork sub-process requires that the sub-process is executed first and share the space with the parent process.
Exit
Exec family functions are used to execute a new application and pass parameters to the new program. You can use man 3 exec to view details.

Wait/waitpid suspends the parent process and waits for the child process to terminate

Checks the macros returned by wait and waitpid.
The wifexited (VAL) sub-process ends normally. The macro returns a non-zero value, indicating that it is true. If the exception ends, 0 is returned, indicating false.
Wexitstus (VAL) If wifexited returns a non-zero value, it returns the low 8 bits of the exit parameter in the sub-process
Wifsignaled (VAL) ends with an exception. If the returned value is not 0, it indicates that it is true.
If the return value of wtermsig (VAL) wifsignaled is not 0, the macro returns the signal number that causes the sub-process to terminate abnormally.
Wifstopped (VAL) sub-process paused. If the returned value is not 0, it indicates that the process is true.
Wstopsig (VAL) wifstopped returns a non-0 value. This macro returns the signal number that suspends the sub-process.

Nice changes the process priority by calling getpriority/setpriority.
Implementation functions:
Int nice (INT increment)
{
Int oldp = getpriority (prio_process, getpid ());
Return setpriority (prio_process, getpid (), oldp + increment );
}

2. Some basic concepts need to be understood. The specific concepts are as follows:

Procedure for converting a program into a process
1. the kernel reads the program into the memory and allocates memory space for the program.
2. the kernel allocates PID and other resources required for the PCB to the process.
3. the kernel saves the PID and status information for the process and puts the process in the running queue for execution.
After the program is converted to a process, it can be scheduled and executed by the scheduling program of the operating system.

Process status (you can view the current user's Process status through PS, such as PS-UX)
R running status
S: interrupted waiting status
D. Do not interrupt wait
Z dead state
T stop status
<High-priority process
N low-priority processes
L Memory Lock page
S session first Process
L multi-threaded Process
+ The process is located in the foreground process group.

To create a daemon, follow these steps:
1. Ignore terminal I/O signals and stop signals
2. End the parent process and make the child process a background process.
3. Use setsid () to create a new process group. In this new process group, the sub-process becomes the first process of the Process Group to remove the process from all terminals.
4. Create a sub-process again and exit the parent process to ensure that the process is not the process leader. At the same time, the process cannot open a new terminal again.
5. Disable all unnecessary file descriptors inherited from the parent process.
6. Change the working directory so that the process does not contact any files.
7. Set the blocked characters to 0.
8. Ignore sigchild Signal

Setsid creates a new dialog period. It is often used to create a daemon. Control terminal, login sessions and process groups are generally inherited from the parent process. The daemon process must get rid of them without being affected. The method is to call setsid to make the process a session leader.

3. Specific code example

// Note: Daemon code
# Include <stdio. h> <br/> # include <sys/types. h> <br/> # include <unistd. h> <br/> # include <signal. h> <br/> # include <sys/Param. h> <br/> # include <sys/STAT. h> <br/> # include <time. h> <br/> # include <syslog. h> <br/> int init_daemon (void) <br/>{< br/> int PID; <br/> int I; <br/>/* ignore terminal I/O signals, stop signals */<br/> signal (sigttou, sig_ign); <br/> signal (sigttin, sig_ign ); <br/> signal (sigtstp, sig_ign); <br/> signal (sighup, sig_ig N); </P> <p> pid = fork (); <br/> If (pid> 0) {<br/> exit (0 ); /* terminate the parent process to make the child process a background process */<br/>}< br/> else if (PID <0) {<br/> return-1; <br/>}< br/>/* Create a new process group. In this new process group, sub-processes become the first process in this process group, to remove the process from all terminals */<br/> setsid (); <br/>/* Create a new sub-process and exit the parent process to ensure that the process is not the process leader, at the same time, the process cannot open a new terminal */<br/> pid = fork (); <br/> If (pid> 0) {<br/> exit (0); <br/>}< br/> else if (PID <0) {<br/> return-1; <br/>}< br/>/* disable all unnecessary file descriptors inherited from the parent process */<br/> For (I = 0; I <nofile; close (I ++); <br/>/* change the working directory, make the process do not contact any file system */<br/> chdir ("/"); <br/>/* set the blocked word created in the file to 0 */<br/> umask (0 ); <br/>/* ignore sigchld signal */<br/> signal (sigchld, sig_ign); </P> <p> return 0; <br/>}< br/> int main () <br/>{< br/> time_t now; <br/> init_daemon (); <br/> syslog (log_user | log_info, "test the daemon! /N "); <br/> while (1) {<br/> sleep (8); <br/> time (& now ); <br/> syslog (log_user | log_info, "system time:/T % S/T/N", ctime (& now )); <br/>}< br/>

// Note: Implementation of myshell

# Include <stdio. h> <br/> # include <stdlib. h> <br/> # include <errno. h> <br/> # include <string. h> <br/> # include <unistd. h> <br/> # include <sys/types. h> <br/> # include <dirent. h> <br/> # include <sys/STAT. h> <br/> # include <fcntl. h> <br/> # include <sys/Wait. h> <br/> # define normal0 <br/> # define out_direct 1 <br/> # define in_direct 2 <br/> # define have_pipe3 <br/> void print_prompt (void ); <br/> void input_argument (char * BUF ); <Br/> void explain_input (char * Buf, int * argcount, char Arglist [100] [256]); <br/> void do_cmd (INT argcount, char Arglist [100] [256]); <br/> int find_command (char * command); <br/> int main () <br/>{< br/> char * Buf; <br/> int argcount; <br/> char Arglist [100] [256]; <br/> If (BUF = (char *) malloc (256) = NULL) {<br/> perror ("malloc error "); <br/> exit (1); <br/>}</P> <p> while (1) {<br/> print_prompt (); <br/> input_ar Gument (BUF); <br/> If (! Strcmp (BUF, "Exit/N") |! Strcmp (BUF, "logout/N") {<br/> printf ("Exit my shell/N"); <br/> break; <br/>}</P> <p> argcount = 0; <br/> explain_input (BUF, & argcount, Arglist); <br/> do_cmd (argcount, arglist); <br/>}</P> <p> free (BUF); </P> <p> return 0; <br/>}< br/> void print_prompt (void) <br/>{< br/> printf ("/n [my shell] $ "); </P> <p >}< br/> void input_argument (char * BUF) <br/>{< br/> char C; <br/> char * l = Buf; <br/> while (C = getchar ())! = '/N') {<br/> * Buf ++ = C; <br/>}< br/> * Buf ++ ='/N '; <br/> * Buf = '/0'; <br/>}< br/> void explain_input (char * Buf, int * argcount, char Arglist [100] [256]) <br/>{< br/> char * P, * q; <br/> int I = 0; <br/> P = Buf; <br/> while (* P! = '/0') {<br/> If (* P ='/N') <br/> break; <br/> If (* P = '') <br/> P ++; <br/> else {<br/> I = 0; <br/> q = P; <br/> while (* Q! = ''& * Q! = '/N') {<br/> Arglist [* argcount] [I ++] = * q; <br/> q ++; <br/>}< br/> Arglist [* argcount] [I] = '/0'; <br/> * argcount + = 1; <br/> P = Q; <br/>}< br/> void do_cmd (INT argcount, char Arglist [100] [256]) <br/>{< br/> int flag = 0; <br/> int flag_count = 0; <br/> pid_t PID; <br/> char * Arg [100]; <br/> int I; <br/> int background = 0; <br/> int status; <br/> Int J; <br/> char * argnext [100]; </P> <p> pid_t pid2; <br/> int F D2; <br/> int status2; </P> <p> for (I = 0; I <argcount; I ++) {<br/> Arg [I] = (char *) Arglist [I]; <br/>}< br/> Arg [argcount] = NULL; </P> <p> for (I = 0; I <argcount; I ++) {<br/> If (strncmp (ARG [I], "&", 1) = 0) {<br/> if (I = argcount-1) {// last words is "&" <br/> background = 1; <br/> Arg [argcount-1] = NULL; <br/> break; <br/>}< br/> else {<br/> printf ("command wrong/N"); <br/> return; <br/>}< br/> for (I = 0; I <argco Unt; I ++) {<br/> If (strcmp (ARG [I], ">") = 0) {<br/> flag_count ++; <br/> flag = out_direct; <br/> If (ARG [I + 1] = NULL) // last words is ">" <br/> flag_count ++; <br/>}< br/> If (strcmp (ARG [I], "<") = 0) {<br/> flag_count ++; <br/> flag = in_direct; <br/> if (I = 0) // first words is "<" <br/> flag_count ++; <br/>}< br/> If (strcmp (ARG [I], "|") = 0) {<br/> flag_count ++; <br/> flag = have_pipe; <br/> // first or last words is "|" <Br/> If (ARG [I + 1] = NULL) <br/> flag_count ++; <br/> if (I = 0) <br/> flag_count ++; <br/>}</P> <p> If (flag_count> 1) {<br/> printf ("flag_count: is % d> 1 so command error/N ", flag_count); <br/> return; <br/>}</P> <p> char * file = NULL; <br/> switch (FLAG) {<br/> case out_direct: <br/> for (I = 0; arg [I]! = NULL; I ++) {<br/> If (strcmp (ARG [I], ">") = 0) {<br/> file = Arg [I + 1]; <br/> Arg [I] = NULL; <br/>}< br/> break; <br/> case in_direct: <br/> for (I = 0; arg [I]! = NULL; I ++) {<br/> If (strcmp (ARG [I], "<") = 0) {<br/> file = Arg [I + 1]; <br/> Arg [I] = NULL; <br/>}< br/> break; <br/> case have_pipe: <br/> // Int J; <br/> // char * argnext [100]; <br/> for (I = 0; arg [I]! = NULL; I ++) {<br/> If (strcmp (ARG [I], "|") = 0) {<br/> Arg [I] = NULL; <br/> for (j = I + 1; arg [J]! = NULL; j ++) {<br/> argnext [j-i-1] = Arg [J]; <br/>}< br/> argnext [j-i-1] = NULL; <br/> break; <br/>}< br/> default: <br/> break; <br/>}</P> <p> int FD; <br/> If (pid = fork () <0) {<br/> printf ("create process error/N"); <br/> exit (1 ); <br/>}< br/> If (pid = 0/* & find_command (ARG [0]) */) {</P> <p> switch (FLAG) {<br/> case normal: <br/> execvp (ARG [0], ARG ); <br/> exit (0); <br/> break; <br/> case out_direct: <br/> If (! Find_command (ARG [0]) {<br/> printf ("command not find/N"); <br/> exit (0 ); <br/>}< br/> FD = open (file, o_rdwr | o_creat | o_trunc, 0644); <br/> printf ("FD: % d/N ", FD); <br/> dup2 (FD, 1); <br/> execvp (ARG [0], ARG); <br/> exit (0 ); <br/> break; <br/> case in_direct: <br/> FD = open (file, o_rdonly); <br/> dup2 (FD, 0 ); <br/> execvp (ARG [0], ARG); <br/> exit (0); <br/> break; <br/> case have_pipe: <br/>/* pid_t pid2; <br/> int fd2; <Br/> int status2; <br/> */<br/> If (pid2 = fork () <0) {<br/> printf ("fork pid2 error/N"); <br/> exit (0 ); <br/>}< br/> If (pid2 = 0) {<br/> If (! Find_command (ARG [0]) {<br/> printf ("command not find/N"); <br/> exit (0 ); <br/>}< br/> fd2 = open ("/tmp/yoursfile", o_creat | o_rdwr | o_trunc, 0644); <br/> dup2 (fd2, 1 ); <br/> execvp (ARG [0], ARG); <br/> exit (0 ); <br/>}</P> <p> If (waitpid (pid2, & status2, 0) =-1) <br/> printf ("wait for child process error/N"); </P> <p> If (! Find_command (argnext [0]) {<br/> printf ("command not find/N"); <br/> exit (0 ); <br/>}</P> <p> fd2 = open ("/tmp/yoursfile", o_rdonly); <br/> dup2 (fd2, 0 ); <br/> execvp (argnext [0], argnext); </P> <p>/* If (remove ("/tmp/yoursfile ")! = 0) {<br/> printf ("Remove File error/N"); <br/>}< br/> exit (0 ); <br/> */break; <br/> default: <br/> break; </P> <p >}</P> <p> // execvp (ARG [0], ARG ); <br/>}</P> <p> If (waitpid (PID, & status, 0) =-1) <br/> printf ("wait for child process error/N"); <br/>}< br/> int find_command (char * command) <br/> {<br/> char * path [] = {". /","/bin ","/usr/bin ", null };< br/> int I = 0; <br/> If (strncmp (". /", command, 2) = 0) <br/> command = Co MmAnd + 2; <br/> dir * dir; <br/> struct dirent * PTR; <br/> while (path [I]! = NULL) {<br/> dir = opendir (path [I]); <br/> while (PTR = readdir (DIR ))! = NULL) {<br/> If (strcmp (PTR-> d_name, command) = 0) {<br/> closedir (DIR); <br/> return 1; <br/>}< br/> closedir (DIR); <br/> I ++; <br/>}</P> <p> return 0; <br/>}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.