<span style="font-size:14px;">#include <unistd.h> pid_t getpid(void); Returns: process ID of calling process pid_t getppid(void); Returns: parent process ID of calling process uid_t getuid(void); Returns: real user ID of calling process uid_t geteuid(void); Returns: effective user ID of calling process gid_t getgid(void); Returns: real group ID of calling process gid_t getegid(void); Returns: effective group ID of calling process</span>
include <fcntl.h> #include <stdio.h> int main() { printf("current process ID:%d\n",getpid()); printf("parent process ID:%d\n",getppid()); printf("real user ID:%d\n",getuid()); printf("effective user ID:%d\n",geteuid()); printf("real group ID:%d\n",getgid()); printf("effective user ID:%d\n",getegid()); return 0; }
#include <unistd.h> pid_t fork(void); Returns: 0 in child, process ID of child in parent,−1 on error
<span style="font-size:14px;">#include"apue.h" int glob = 6; char buf[] = "a write to stdout\n"; int main(int argc ,char* argv[]) { int var; pid_t pid; var = 88; if(write(STDOUT_FILENO,buf,sizeof(buf)-1) != sizeof(buf)-1) { printf("write error"); } printf("before fork\n"); if((pid = fork()) < 0) { printf("fork error"); } else if(pid == 0) { glob++; var++; } else { sleep(2); } printf("pid = %d glob = %d var = %d\n",getpid(),glob,var); return 0; }</span><span style="font-size:18px;"> </span>
•Real user ID, real group ID, effective user ID, and effective group ID•Supplementary group IDs•Process group ID•Session ID•Controlling terminal•The set-user-ID and set-group-ID flags•Current working directory•Root directory•File mode creation mask•Signal mask and dispositions•The close-on-exec flag for any open file descriptors•Environment•Attached shared memory segments•Memory mappings•Resource limits
•The return values from fork are different.•The process IDs are different.•The two processes have different parent process IDs: the parent process ID of the child is the parent; the parent process ID of the parent doesn’t change.•The child’s tms_utime, tms_stime, tms_cutime, and tms_cstime values are set to 0•File locks set by the parent are not inherited by the child.•Pending alarms are cleared for the child.•The set of pending signals for the child is set to the empty set.
1. When a process wants to duplicate itself so that the parent and the child can each execute different sections of code at the same time.2. When a process wants to execute a different program.
The vfork function creates the new process, just like fork,without copying the address space of the parent into the child, as the child won’t reference that address space; the child simply calls exec (or exit)right after the vfork. Instead, the child runs in the address space of the parent until it calls either exec or exit
#include"apue.h" #include"myerr.h" int glob = 6; int main() { int var; pid_t pid; var = 88; printf("before fork!\n"); if((pid = vfork()) < 0) { err_sys("vfork error\n"); } else if(pid == 0) { glob++; var++; _exit(0); } printf("pid = %d,glob = %d,var = %d\n",getpid(),glob,var); exit(0); }
1. Executing a return from the main function. This is equivalent to calling exit.
2. Calling the exit function. This function is defined by ISO C and includes the calling of all exit handlers that have been registered by calling at exit and closing all standard I/O streams.
3. Calling the _exit or _Exit function. _Exit to provide a way for a process to terminate without running exit handlers or signal handlers. Whether standard I/O streams are flushed depends on the implementation.
4. Executing a return from the start routine of the last thread in the process.
5. Calling the pthread_exit function from the last thread in the process.
1. Calling abort
2. When the process receives certain signals.
3. The last thread responds to a cancellation request.
•Block, if all of its children ar estill running
•Return immediately with the termination status of a child, if a child has terminated and is waiting for its termination status to be fetched
•Return immediately with an error, if it doesn’t have any child processes
<span style="font-size:14px;">#include <sys/wait.h> pid_t wait(int *statloc ); pid_t waitpid(pid_t pid,int *statloc ,int options ); Both return: process ID if OK, 0 (see later), or −1 on error</span>下面是linux里面对于waitpid的解释
<span style="font-size:14px;">#include"apue.h" #include"pr_exit.h" #include"myerr.h" #include<sys/wait.h> int main () { pid_t pid; int status; if((pid = fork()) < 0) { err_sys("fork error\n"); } else if(pid == 0) { exit(7); } if(wait(&status) != pid) { err_sys("wait pid\n"); } pr_exit(status); if((pid = fork()) < 0) { err_sys("wait error\n"); } else if(pid == 0) { abort(); } if(wait(&status) != pid) { err_sys("wait pid\n"); } pr_exit(status); if((pid = fork()) < 0) { err_sys("fork error\n"); } else if(pid == 0) { status /= 0; } if(wait(&status) != pid) { err_sys("wait error\n"); } pr_exit(status); exit(0); }</span>pr_exit.h 文件的实现:
#ifndef _PR_EXIT_H #define _PR_EXIT_H #include"apue.h" #include<sys/wait.h> void pr_exit(int status) { if(WIFEXITED(status)) { printf("normal termination,exit status = %d\n",WEXITSTATUS(status)); } else if(WIFSIGNALED(status)) { printf("abnormal termination,signal number =%d%s\n",WTERMSIG(status), #ifdef WCOREDUMP WCOREDUMP(status) ? "(core file generated)" : " "); } #else " "); } #endif else if(WIFSTOPPED(status)) { printf("child stopped,signal number = %d\n",WSTOPSIG(status)); } } #endif
<span style="font-size:14px;">#include"apue.h" #include"myerr.h" #include"stdio.h" #include<sys/wait.h> int main() { pid_t pid; if((pid = fork()) < 0) { err_sys("forkerror!\n"); } else if(pid == 0) { if((pid = fork()) < 0) { err_sys("forkerror\n"); } else if(pid > 0) { /* if(waitpid(pid,NULL,0) != pid) { printf("waitpid error\n"); } printf("firstchild pid = %d\n",getpid()); */ exit(0); } sleep(2); printf("\nsecond child, parentgetppid =%d second child pid = %d\n",getppid(),getpid()); exit(0); } if(waitpid(pid,NULL,0) != pid) { err_sys("waitpiderror\n"); } printf("parent pid = %d\n",getppid()); exit(0); }</span>
The wait()system call suspends execution of the calling process until one of its childrenterminates. The call wait(&status) is equivalent to: waitpid(-1, &status, 0);
#include <sys/wait.h> int waitid(idtype_t idtype ,id_t id ,siginfo_t *infop,int options ); Returns: 0 ifOK,−1 on error
Instead of encoding this information in a single argument combined with the process ID or process group ID, two separate arguments are used.
<span style="font-size:14px;">/************************************************************* code writer :EOF code date :2014.03.28 e-mail:[email protected] code purpose : I just share my demo with who isinteresting in APUE. Open source makethe world more beautiful. I would like to recept yourfeedback, if there is something wrong with my code. Please touch meby e-mail. Thank you *************************************************************/ #include<stdio.h> #include<apue.h> #include<sys/wait.h> #include<stdlib.h> #include<signal.h> int main() { int pid = 0; int status = 0; siginfo_t* p_siginfo = NULL; p_siginfo =(siginfo_t*)malloc(sizeof(siginfo_t)); if(p_siginfo == NULL) { printf("malloc error\n"); return 0; } if((pid = fork()) < 0) { printf("forkerror\n"); } else if(pid == 0) { printf("hello! I am thechild %d\n",getpid()); exit(0); } /* if(waitpid(pid,&status,0) < 0 ) { printf("waitpiderror\n"); } */ int temp = 0; if((temp =waitid(P_PID,pid,p_siginfo,0)) < 0)// why there would return -1 { printf("waitiderror\n"); } if(WIFEXITED(status)) { printf("normallytermination,exit status = %d\n",status); } printf("parent exit\n"); free(p_siginfo); return 0; }</span>
写了个demo,但是不知道waitid的哪个地方错了。老是提示waitid错误
For our purposes, a race condition occurs when multiple processes aretrying to do something with shared data and the final outcome depends on the order in which the processes run.
</pre><pre name="code" class="cpp">#include <apue.h> #include<stdio.h> #include<myerr.h> static void charatatime(char*); int main() { pid_t pid; if((pid = fork()) < 0) { err_sys("forerror\n"); } else if(pid == 0) { charatatime("output fromchild\n"); } else { charatatime("output fromparent\n"); } return 0; } static void charatatime(char*str) { char * ptr; int c ; setbuf(stdout,NULL); for(ptr = str;(c = *ptr++) != 0;) { putc(c,stdout); } }
Test result
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_8$./a.out
ououttppuutt ffrom child
rom parent
#include <unistd.h> int execl(const char *pathname ,const char *arg0 ,... /* (char *)0 */ ); int execv(const char *pathname ,char *constargv []); int execle(const char * pathname ,const char *arg0 ,... /* (char *)0, char *constenvp [] */ ); int execve(const char * pathname ,char *constargv [], char *constenvp []); int execlp(const char * filename,const char *arg0 ,... /* (char *)0 */ ); int execvp(const char * filename,char *constargv []); int fexecve(intfd ,char *constargv [], char *constenvp []); All seven return:−1 on error, no return on success
•If filename contains a slash, it is taken as a pathname.
•Otherwise, the executable file is searched for in the directories specified by the PATH environment variable.
•Process ID and parent process ID•Real user ID and real group ID•Supplementary group IDs•Process group ID•Session ID•Controlling terminal•Time left until alarm clock•Current working directory•Root directory•File mode creation mask•File locks•Pro cess signal mask•Pending signals•Resource limits•Nice value (on XSI-conformant systems; see Section 8.16)•Values for tms_utime, tms_stime, tms_cutime,andtms_cstime
<span style="font-size:14px;">/**************************************************************** code writer : EOF code date : 2014.03.27 e-mail: [email protected] attention: The ./a.out ./b.out problem is just simple "hello world" program.If you want to use another program to repleace the program it is OK. ****************************************************************/ #include"apue.h" #include"myerr.h" #include"sys/wait.h" char* env_init[] = {"USER=unknown" ,"PATH=/tmp",NULL}; int main() { pid_t pid; if((pid = fork()) < 0) { err_sys("fork error\n"); } else if( pid == 0) { if(execle("./a.out","a.out",(char*)0,env_init) < 0) { err_sys("execle error\n"); } } else { if(waitpid(pid,NULL,0) < 0) { err_sys("wait error\n"); } printf("parent\n"); } if((pid = fork()) < 0) { err_sys("fork error\n"); } else if(pid == 0) { if(execlp("./b.out","b.out",(char*) 0) < 0) { err_sys("execlp error\n"); } } else { if(waitpid(pid,NULL,0) < 0) { err_sys("wait error\n"); } printf("parent\n"); } exit(0); }</span>
<span style="font-size:14px;">#include <unistd.h> int setuid(uid_t uid); int setgid(gid_t gid); Both return: 0 if OK, −1 on error</span>
#! pathname [ optional-argument ]
<span style="font-size:14px;">#! /usr/bin/awk -f BEGIN { for(i = 0;i< ARGC;i++) { printf("ARGV[%d] = %s\n",i,ARGV[i]); } exit(0); }</span><span style="font-size:18px;"> </span>
<span style="font-size:14px;">#include"apue.h" #include"sys/wait.h" #include"myerr.h" int main() { pid_t pid; if((pid = fork()) < 0) { err_sys("fork error!\n"); } else if(pid == 0) { //if(execl("/Ad_Pro_in_Unix/chapter_8/awkexample","awkexample",NULL) < 0)//this is for figure-21 if(execl("./testinterp","testinterp",NULL) < 0)//this is fir figure-20 { err_sys("execl error!\n"); } } if(waitpid(pid,NULL,0) < 0) { err_sys("waitpid error!\n"); } exit(0); }</span><span style="font-size:18px;"> </span>testinterp:
#! ./a.out
#include <stdlib.h> int system(const char * cmdstring); Returns: (see below)
1. If either the fork fails or waitpid returns an error other than EINTR, system are turns −1 with errno set to indicate the error.
2. If the exec fails, implying that the shell can’t be executed, the return value is as if the shell had executed exit(127).
3. Otherwise, all three functions—fork, exec,and waitpid—succeed, and the return value from system is the termination status of the shell, in the format specified for waitpid.
<span style="font-size:14px;">#include<sys/wait.h> #include<errno.h> #include<unistd.h> int system(const char* cmdstring) { pid_t pid; int status; if(cmdstring == NULL) { return (1); } if((pid = fork()) < 0) { status = -1; } else if(pid == 0) { execl("/bin/sh","sh","-c",cmdstring,NULL); _exit(127); } else { while(waitpid(pid,&status,0) < 0) { if(errno != EINTR) { status = -1; break; } } } return (status); }</span><span style="font-size:18px;"> </span>
<span style="font-size:14px;">#include<sys/wait.h> #include<errno.h> #include<unistd.h> int system(const char* cmdstring) { pid_t pid; int status; if(cmdstring == NULL) { return (1); } if((pid = fork()) < 0) { status = -1; } else if(pid == 0) { execl("/bin/sh","sh","-c",cmdstring,NULL); _exit(127); } else { while(waitpid(pid,&status,0) < 0) { if(errno != EINTR) { status = -1; break; } } } return (status); }</span>
<span style="font-size:14px;">#include"apue.h" #include"myerr.h" #include"pr_exit.h" int main(int argc,char* argv[]) { int status; if(argc < 2) { err_quit("command-line argument required"); } if((status = system(argv[1])) < 0) { err_sys("system() error\n"); } pr_exit(status); exit(0); }</span>
<span style="font-size:14px;">#include"apue.h" #include"stdio.h" int main() { printf("real uid = %d,effective uid = %d\n",getuid(),geteuid()); exit(0); }</span>
#include <unistd.h> int acct(const char *filename); On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
<span style="font-size:14px;">struct acct { char ac_flag; /* Flags. */ u_int16_t ac_uid; /* Real user ID. */ u_int16_t ac_gid; /* Real group ID. */ u_int16_t ac_tty; /* Controlling terminal. */ u_int32_t ac_btime; /* Beginning time. */ comp_t ac_utime; /* User time. */ comp_t ac_stime; /* System time. */ comp_t ac_etime; /* Elapsed time. */ comp_t ac_mem; /* Average memory usage. */ comp_t ac_io; /* Chars transferred. */ comp_t ac_rw; /* Blocks read or written. */ comp_t ac_minflt; /* Minor pagefaults. */ comp_t ac_majflt; /* Major pagefaults. */ comp_t ac_swaps; /* Number of swaps. */ u_int32_t ac_exitcode; /* Process exitcode. */ char ac_comm[ACCT_COMM+1]; /* Command name. */ char ac_pad[10]; /* Padding bytes. */ };</span>
<span style="font-size:14px;">enum { AFORK = 0x01, /* Has executed fork, but no exec. */ ASU = 0x02, /* Used super-user privileges. */ ACORE = 0x08, /* Dumped core. */ AXSIG = 0x10 /* Killed by a signal. */ };</span>
#include <apue.h> #include <sys/wait.h> #include <sys/acct.h> #include <myerr.h> #ifdef HAS_SA_STAT #define FMT "%-*.*s e = %6ld,chars = %7ld,stat = %3u: %c %c %c %c\n" #else #define FMT "%-*.*s e = %6ld,chars = %7ld,%c %c %c %c\n" #endif #ifndef HAS_ACORE #define ACORE 0 #endif #ifndef HAS_AXSIG #define AXSIG 0 #endif static unsigned long compt2ulong(comp_t comptime) { unsigned long val; int exp; val = comptime & 0x1fff; exp = (comptime >> 13) & 7; while(exp-- >0) { val *= 8; } return (val); } int main(int argc,char* argv[]) { struct acct acdata; FILE *fp; if(argc != 2) { err_quit("usage: pracct filename"); } if((fp = fopen(argv[1],"r")) == NULL) { err_sys("can't open %s",argv[1]); } while(fread(&acdata,sizeof(acdata),1,fp) ==1) { printf(FMT,(int)sizeof(acdata.ac_comm),(int)sizeof(acdata.ac_comm),acdata.ac_comm,compt2ulong(acdata.ac_etime),compt2ulong(acdata.ac_io), #ifdef HAS_STAT (unsigned char) acdata.ac_stat, #endif acdata.ac_flag & ACORE ? 'D' :' ', acdata.ac_flag & AXSIG ? 'X' :' ', acdata.ac_flag & AFORK ? 'F' :' ', acdata.ac_flag & ASU ? 'S' :' '); } if(ferror(fp)) { err_sys("read error\n"); } exit(0); }
#include <unistd.h> char *getlogin(void); Returns: pointer to string giving login name if OK,NULL on error
<span style="font-size:14px;">#include <stdio.h> #include <unistd.h> int main() { printf("the user login: %s\n",getlogin()); return 0; }</span><span style="font-size:18px;"> </span>
#include <sys/times.h> clock_t times(struct tms *buf ); Returns: elapsed wall clock time in clock ticks if OK,−1 on error
struct tms { clock_t tms_utime; /* user CPU time */ clock_t tms_stime; /* system CPU time */ clock_t tms_cutime; /* user CPU time, terminated children clock_t tms_cstime; /* system CPU time, terminated childr };
#include"apue.h" #include"myerr.h" #include"pr_exit.h" #include <sys/times.h> static void pr_times(clock_t,struct tms*, struct tms*); static void do_cmd(char*); int main (int argc ,char* argv[]) { int i; setbuf(stdout,NULL); for(i =1;i< argc ;i++) { do_cmd(argv[i]); } exit(0); } static void do_cmd(char* cmd) { struct tms tmsstart,tmsend; clock_t start,end; int status; printf("\ncommand:%s\n",cmd); if((start = times(&tmsstart)) == -1) { err_sys("times error\n"); } if((status = system(cmd)) < 0) { err_sys("system() error\n"); } if((end = times(&tmsend)) == -1) { err_sys("times error\n"); } pr_times(end-start,&tmsstart,&tmsend); pr_exit(status); } static void pr_times(clock_t real,struct tms* tmsstart,struct tms* tmsend) { static long clktck = 0; if(clktck == 0) { if((clktck = sysconf(_SC_CLK_TCK)) < 0) { err_sys("sysconf error\n"); } printf(" real: %7.2f\n",real / (double) clktck); printf(" user: %7.2f\n", (tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck); printf(" sys: %7.2f\n", (tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck); printf(" child user: %7.2f\n", (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck); printf(" child sys: %7.2f\n", (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck); } }