Use the C language fork () function to create an instance of a process in Linux to explain the _c language

Source: Internet
Author: User
Tags semaphore wrappers file permissions

The only way to create a new process in Linux is to use the fork () function. The fork () function is a very important function in Linux, and there are some differences from previous functions, because the fork () function looks like it executes once but returns two values.

The fork () function is used to create a new process from an existing process. The new process is called a subprocess, and the garden process is called the parent process. A child process obtained using the fork () function is a replica of the parent process. It inherits the entire process's address space from the parent process, including the context of the process, code snippets, process stacks, memory information, open file descriptors, symbol control settings, process priority, process group number, current working directory, root directory, Resource constraints and control terminals, and the child processes are unique only to its process number, resource usage, and timers.

Because the child process is almost completely replicated by the parent process, the parent-child process runs the same program. This requires a way to differentiate them and make them run like this, otherwise the two processes cannot do different things. In effect, when the fork () function is executed in the parent process, the parent process replicates a child process, and the code of the parent-child process runs concurrently in the two address spaces, starting with the return of the fork () function, so that two processes get the return value of the fork () function of the owning The return value in the parent process is the process number of the child process, and returns 0 in the child process. Therefore, you can determine whether the process is a parent or a child by returning a value.

At the same time, it can be seen that the cost of using the fork () function is great, it replicates most of the code snippets, data segments, and stack segments in the parent process, making the fork () function more expensive and not fast.

Fork () function syntax

There may be two reasons why the fork () function is wrong:
1, the current number of processes has reached the upper limit of the system, when the value of errno is set to Eagain
2, the system memory is not enough, at this time errno value is set to Enomem

Example

The following is the Csapp.h header file, which is only used to complete the program in subsequent discussions.

/* $begin csapp.h * * #ifndef __csapp_h__ #define __CSAPP_H__ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <setjmp.h> #include <signal.h > #include <sys/time.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> # Include <fcntl.h> #include <sys/mman.h> #include <errno.h> #include <math.h> #include < pthread.h> #include <semaphore.h> #include <sys/socket.h> #include <netdb.h> #include <netinet /in.h> #include <arpa/inet.h>/* Default file permissions are Def_mode & ~def_umask/* $begin Createmask S */#define DEF_MODE s_irusr| s_iwusr| s_irgrp| s_iwgrp| s_iroth| S_iwoth #define Def_umask s_iwgrp|  S_iwoth/* $end createmasks/* Simplifies calls to bind (), connect (), and accept ()////* $begin Sockaddrdef/typedef
struct SOCKADDR SA; /* $end Sockaddrdef//////* Persistent State for THe robust I/O (Rio) package///* $begin rio_t/* #define RIO_BUFSIZE 8192 typedef struct {int rio_fd;        /* Descriptor for this internal BUF */int rio_cnt;     /* Unread bytes in internal buf */char *rio_bufptr; /* Next unread byte in internal BUF */char rio_buf[rio_bufsize];
* Internal buffer */} rio_t;  * * $end rio_t *////* External variables/extern int h_errno; /* Defined by BIND for DNS errors */extern char **environ;  /* Defined by LIBC/* Misc Constants/* Maxline 8192/* Max Text line length * * #define MAXBUF 8192/* max I/O buffer size/#define LISTENQ 1024/* Second argument to listen () * * * our own error-handling/void UN
Ix_error (char *msg);
void Posix_error (int code, char *msg);
void Dns_error (char *msg);

void App_error (char *msg);
/* Process Control wrappers */pid_t Fork (void);
void Execve (const char *filename, char *const argv[], char *const envp[]);
pid_t Wait (int *status); pid_t waitpid (pid_t pid, int *iptr, int options);
void Kill (pid_t pid, int signum);
unsigned int sleep (unsigned int secs);
void Pause (void);
unsigned int Alarm (unsigned int seconds);
void Setpgid (pid_t pid, pid_t pgid);

pid_t getpgrp ();
/* Signal wrappers */typedef void handler_t (int);
handler_t *signal (int signum, handler_t *handler);
void Sigprocmask (int how, const sigset_t *set, sigset_t *oldset);
void Sigemptyset (sigset_t *set);
void Sigfillset (sigset_t *set);
void Sigaddset (sigset_t *set, int signum);
void Sigdelset (sigset_t *set, int signum);

int Sigismember (const sigset_t *set, int signum);
/* Unix I/o wrappers/int Open (const char *pathname, int flags, mode_t mode);
ssize_t Read (int fd, void *buf, size_t count);
ssize_t Write (int fd, const void *buf, size_t count);
off_t lseek (int fildes, off_t offset, int whence);
void Close (int fd);
int Select (int n, fd_set *readfds, Fd_set *writefds, Fd_set *exceptfds, struct timeval);
int Dup2 (int fd1, int fd2); void Stat (const char *filename, struct STAT*BUF);

void Fstat (int fd, struct stat *buf);
/* Memory mapping wrappers/void *mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset);

void Munmap (void *start, size_t length);
/* Standard I/o wrappers/void Fclose (FILE *fp);
FILE *fdopen (int fd, const char *type);
Char *fgets (char *ptr, int n, FILE *stream);
FILE *fopen (const char *filename, const char *mode);
void Fputs (const char *ptr, FILE *stream);
size_t Fread (void *ptr, size_t size, size_t nmemb, FILE *stream);

void fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream);
/* Dynamic Storage allocation wrappers/void *malloc (size_t size);
void *realloc (void *ptr, size_t size);
void *calloc (size_t nmemb, size_t size);

void free (void *ptr);
/* Sockets Interface wrappers */int Socket (int domain, int type, int protocol);
void setsockopt (int s, int level, int optname, const void *optval, int optlen);
void Bind (int sockfd, struct sockaddr *my_addr, int addrlen);
void Listen (int s, int backlog); IntAccept (int s, struct sockaddr *addr, socklen_t *addrlen);

void Connect (int sockfd, struct sockaddr *serv_addr, int addrlen);
/* DNS wrappers */struct hostent *gethostbyname (const char *name);

struct hostent *gethostbyaddr (const char *addr, int len, int type); /* Pthreads Thread control wrappers */void Pthread_create (pthread_t *tidp, pthread_attr_t *attrp, void * (*routine
) (void *), void *ARGP);
void Pthread_join (pthread_t tid, void **thread_return);
void Pthread_cancel (pthread_t tid);
void Pthread_detach (pthread_t tid);
void Pthread_exit (void *retval);
pthread_t pthread_self (void);

void Pthread_once (pthread_once_t *once_control, Void (*init_function));
/* POSIX semaphore wrappers */void Sem_init (sem_t *sem, int pshared, unsigned int value);
void P (sem_t *sem);

void V (sem_t *sem);
/* RIO (Robust I/O) package/ssize_t rio_readn (int fd, void *usrbuf, size_t n);
ssize_t rio_writen (int fd, void *usrbuf, size_t n); 
void Rio_readinitb (rio_t *rp, int fd); ssize_t RIO_READNB(rio_t *rp, void *usrbuf, size_t n);

ssize_t Rio_readlineb (rio_t *rp, void *usrbuf, size_t maxlen);
/* Wrappers for Rio Package * * ssize_t rio_readn (int fd, void *usrbuf, size_t n);
void Rio_writen (int fd, void *usrbuf, size_t n); 
void Rio_readinitb (rio_t *rp, int fd);
ssize_t RIO_READNB (rio_t *rp, void *usrbuf, size_t n);

ssize_t Rio_readlineb (rio_t *rp, void *usrbuf, size_t maxlen);
/* Client/server helper functions */int open_clientfd (char *hostname, int portno);

int open_listenfd (int portno);
/* Wrappers for Client/server helper functions */int open_clientfd (char *hostname, int port); 

int open_listenfd (int port);

 #endif/* __csapp_h__ * * $end csapp.h * *

Fork () Function Example a

#include "csapp.h" 
int main ()
{
 pid_t pid;
 int x=1;
 Pid=fork ();
 if (pid==0) {
  printf ("child:x=%d\n", ++x);
  Exit (0);
 }
 printf ("parent:x=%d\n",--x);
 Exit (0);
}

For example, the above program, because the fork () function is more special, executes once, returns two times. Returns two times, each of which returns a value in the parent and child processes, returns 0 in the subprocess, and returns the process ID in the parent process, typically a positive integer or Non-zero. This allows you to determine in which process it is based on the return value. As the above procedure, pid=0, so the IF statement is executed, the child process shares the parent process's text/data/BSS segment/heap, and the user stack, the child process terminates normally and the return code is 0, so the child process does not execute subsequent shared blocks of code, so the output of this program is

Parent:x=0
child:x=2

Fork () Function Example Two

#include "csapp.h"

int main ()
{
 if (fork () ==0) {
  printf ("a");
 }
 else {
  printf ("B");
  Waitpid ( -1,null,0);
 }
 printf ("C");
 Exit (0);
}

This program is used to verify the relationship between the child process and the parent process. Again, again, the fork () function is used to create a new subprocess that has the same user-level virtual address space as the parent process, including the text/Data/BSS segment/heap/user stack, where the child processes can read and write files opened by any parent process, the biggest difference being that they have different PID. Fork function call once, return two times, the PID of the child process is returned once in the parent process; In the subprocess, fork returns 0 because the PID of the child process is always non-zero, and the return value provides an explicit way to tell whether it is executing in a parent process or in a child process. The Waitpid () function is to wait for the child process to terminate, and if there is no error, the return value is positive. Because in the subprocess, fork () returns 0, so it outputs a, and it shares the code snippet of the parent process, and then outputs C, and in the parent process, the fork () returns a Non-zero value, so it executes the else statement, so it outputs the BC. Therefore, the output of this program is
acbc

Fork () Function Example Three

#include "csapp.h"
int main ()
{
 int x=1;
 if (fork () ==0)
  printf ("printf1:x=%d\n", ++x);
 printf ("printf2:x=%d\n",--x);
 Exit (0);
}

This program again demonstrates the difference between a subprocess and a parent process. Program in which the child processes share the data x=1, and fork () returns 0, so if statements are executed, the output is printf1:x=2, then the subsequent portion of the snippet is shared, and then the Printf2:x=1 is returned, and for the parent process, fork () returns Non-zero. As a result, the If statement segment is not executed, and the following code is executed, which is the output printf2:x=0. Therefore, the output of this program is (subprocess and parent process order is not unique)

Printf2:x=0
printf1:x=2
printf2:x=1

Fork () Function Example Four

#include "csapp.h"
#define N 3
int main ()
{
 int status,i;
 pid_t pid; 

 for (i=0;i<n;i++)
  if ((Pid=fork ()) ==0)//new child process
   exit (100+i); 

 while ((Pid=waitpid ( -1,&status,0)) >0) {//If the child process is terminated normally, it returns the process number PID
  if (wifexited (status))//Return exit status
   printf ("Child%d terminated normally with exit status =%d\n", Pid,wexitstatus (status));
  else
   printf ("Child%d erminated abnormally\n", PID);
 }

 if (errno!=echild)
  printf ("Waitpid error\n");
 Exit (0);
}

This code is mainly the termination of the test process, that is, the Waitpid case program. The definition generates two processes, and this example does not recycle zombie processes in a particular order, and this program returns the result

Child 28693 terminated normally with exit status =100 child 28694 terminated normally with
exit status =101
chil D 28695 terminated normally with exit status =102

Fork () Function Example Five

#include "csapp.h"
#define N 2
int main ()
{
 int status,i;
 pid_t Pid[n],retpid;

 for (i=0;i<n;i++)
  if ((Pid[i]=fork ()) ==0) Exit
   (100+i);//exit and return status code
 i=0;
 while ((Retpid=waitpid (pid[i++],&status,0)) >0) {
  if (wifexited (status))
   printf (' Child%d Terminated normally with exit status=%d\n ", Retpid,wexitstatus (status));
  else
   printf ("Child%d terminated abnormally\n", retpid);
 }

 if (errno!=echild)
  printf ("Waitpid error!");
 Exit (0);
}

In order to create processes to reclaim these zombie processes, note that the program in the pid[i++] is a sequential flag, this program to run the results of

Child 29846 terminated normally with exit status=100 child 29847 terminated normally with
exit status=101

Fork () Function Example Six

#include "csapp.h"

/* Guesses what result this program will output *

/int main ()
{
 int status;
 pid_t pid;

 printf ("hello\n");
 Pid=fork ();
 printf ("%d\n",!pid);
 if (pid!=0) {
  if (waitpid ( -1,&status,0) >0) {
   if (wifexited (status)!=0)
  printf ("%d\n", Wexitstatus (status));
  }
 printf ("bye\n");
 Exit (2);
}

First the parent process outputs Hello, the child process is new successfully, in the subprocess, the PID is 0, the output is 1, and the child process cannot execute the IF statement, but the child process can still output bye and the status code is returned normally to 2. In the parent process, the PID is a non-zero positive number, so first output 0, and then execute the IF statement, because the child process has been normal exit, so the output status code 2, and the final execution of public code block, output bye and normal exit. Therefore, the results of the total output are as follows:

Hello
0
1
Bye
2
Bye

Of course, the order is not unique, there is a possible result is

Hello
1
Bye
0
2
Bye

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.