简单的fork例子
#include <iostream> #include <unistd.h> #include <sys/types.h> using namespace std; int main() { pid_t pid; pid=fork(); cout<<"fork()"<<endl; return 0; }输出:
fork() fork()
#include <iostream> #include <unistd.h> #include <sys/types.h> using namespace std; int main() { pid_t pid; switch(pid=fork()) { case 0 :cout<<"child:"<<pid<<endl;break; case -1:cout<<"error!"<<endl;break; default:cout<<"parent:"<<pid<<endl;break; } return 0; }
parent:9743 child:0
产生子进程之后可以通过exec系列函数执行其他功能程序。
exec系列函数:int execl( const char *path, const char *arg, ...); 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[]);
#include <iostream> #include <unistd.h> using namespace std; int main() { cout<<"开始执行"<<endl; execl("/bin/date","date","-d","2012/12/12",NULL); cout<<"这句不会执行"<<endl; return 0; }
开始执行 2012年 12月 12日 星期三 00:00:00 CST
#include <iostream> #include <unistd.h> #include <sys/types.h> using namespace std; int main() { pid_t pid; switch(pid=fork()) { case 0 : { cout<<"child!"<<endl; execl("/bin/date","date","-d","2012/12/12",NULL);//执行execl调用 cout<<"这句不会执行"<<endl; } case -1:cout<<"error!"<<endl;break; default:cout<<"parent!"<<endl;break; } return 0; }
parent! child! 2012年 12月 12日 星期三 00:00:00 CST
在fork之后exec之前,两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。所以子进程中的所有变量均保持它们在父进程中之值(fork()的返回值除外)。
当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段会分配单独的物理空间。
如果设置了执行关闭位(close-on-exec)的话,调用 exec 时会关闭相应的文件。该位的默认值为非设置。
文件指针示例#include <iostream> #include <unistd.h> #include <wait.h> #include <sys/types.h> #include <fcntl.h> using namespace std; int main() { int fd; int pid; char buf[1]={‘\0‘}; if ((fd=open("data.txt",O_RDONLY))<0) {//data里面仅有两个字符‘1’和‘2’ perror("open failed"); exit(1); } pid=fork(); if (pid<0) perror("fork failed"); else if (pid==0) { read(fd,buf,1);//读取1 cout<<buf<<endl; } else { wait(NULL);//读取2 read(fd,buf,1); cout<<buf<<endl; } }
1 2
exit函数
exit()只有一个参数status,称作进程的退出状态,父进程可以使用它的低 8 位。注意,在整型量中,低 8 位在前,高 8 位在后
exit函数示例
#include <iostream> #include <unistd.h> #include <wait.h> #include <sys/types.h> using namespace std; int main() { pid_t pid; switch(pid=fork()) { case 0 : { exit(1);//设置退出状态 break; } case -1:cout<<"error!"<<endl;break; default: { int statue; wait(&statue); //获取低8位 statue=statue>>8; statue=statue & 0xff; cout<<statue<<endl; break; } } return 0; }
1
wait函数
当子进程执行时,wait函数可以暂停父进程的执行,使起等待。一旦子进程执行完,等待的父进程就会继续执行。如果有多个子进程在执行,那么父进程中的 wait()在第一个子进程结束时返回,恢复父进程执行。通常情况下,父进程调用 fork()后要调用 wait()。
wait示例#include <iostream> #include <unistd.h> #include <wait.h> #include <stdio.h> #include <sys/types.h> #include <fcntl.h> using namespace std; int main() { pid_t pid; switch(pid=fork()) { case 0 : { cout<<"1"<<endl; break; } case -1:cout<<"error!"<<endl;break; default: { switch(pid=fork()) { case 0 : { sleep(1); cout<<3<<endl; break; } case -1:cout<<"error!"<<endl;break; default: //产生了两个子进程,但在第一个进程返回时,开始执行 wait(NULL); cout<<2<<endl; break; } } } return 0; }
1 2 3
在子进程终止时,根据父进程的状态,子进程有两种不同的状态
1.子进程终止时,父进程并不正在执行 wait()调用。
2.当子进程尚未终止时,父进程却终止了。
第一种状态就是所谓的僵尸进程。处于这种状态的进程不使用任何内核资源,但是要占用内核中的进程处理表那一项。直到其父进程执行wait()操作时,把这种处于僵尸状态的进程从系统内删除,子进程才算真正的退出,而其父进程仍将能得到该子进程的结束状态。
在第二种情况中,一般允许父进程结束时,把它的子进程(包括处于僵尸状态的进程)交归系统的初始化进程所属。
僵尸进程示例#include <iostream> #include <unistd.h> #include <wait.h> #include <sys/types.h> using namespace std; int main() { pid_t pid; switch(pid=fork()) { case 0 : { exit(1); break; } case -1:cout<<"error!"<<endl;break; default: { int statue; sleep(10); wait(&statue); statue=statue>>8; statue=statue & 0xff; cout<<statue<<endl; break; } } return 0; }
1
int setpgrp(void);设置新的进程组标识符 int getpgrp(void);获得其当前的进程组标识符
在使用 environ 指针前,应该首先声明它:extern char **environ;
environ示例:#include <iostream> #include <unistd.h> #include <wait.h> #include <sys/types.h> using namespace std; extern char** environ; int main() { char** env=environ; cout<<env[1]<<endl; return 0; }
USER=root
int daemon(int nochdir, int noclose); 1. daemon()函数主要用于希望脱离控制台,以守护进程形式在后台运行的程序。 2. 当nochdir为0时,daemon将更改进程的根目录为root(“/”)。 3. 当noclose为0是,daemon将进程的STDIN, STDOUT, STDERR都重定向到/dev/null。
void daemon() { int i: pid_t pid; if (pid=fork()) exit(0);/* fork,终止父进程 */ /* 第一子进程 */ setsid();//创建了一个新的进程组,调用进程成了该进程组的首进程 signal(SIGHUP,SIG_IGN); if (pid=fork()) exit(0);/* fork,终止第一子进程 */ /* 第二子进程 脱离控制终端*/ chdir("/");/* 将工作目录设定为"/" */ umask(0);/* 清除文件掩码 */ /* 关闭所有文件句柄 */ for (i=0;i<MAXFD;i++) { close(i); } }
linux之多线程frok(一),布布扣,bubuko.com
原文地址:http://blog.csdn.net/zsp_skyer/article/details/26147271