程序中,我们有时需要启动一个新的进程,来完成其他的工作。
下面介绍了三种实现方法,以及这三种方法之间的区别。
1.system函数-调用shell进程,开启新进程
system函数,是通过启动shell进程,然后执行shell命令进程。
原型:
int system(const char *string);
string:shell命令字符串
返回值:成功返回命令退出码,无法启动shell,返回127错误码,其他错误,返回-1。
代码示例如下:
process_system.c
#include<stdlib.h> #include<stdio.h> int main() { printf("Running ps with system\n"); int code = system("ps au");//新进程结束后,system函数才返回 //int code = system("ps au");//system函数立即返回 printf("%d\n",code); printf("ps Done\n"); exit(0); }
输出结果:
system函数,在启动新进程时,必须先启动shell进程,因此使用system函数的效率不高。
2.exec系列函数-替换进程映像
exec系列函数调用时,启动新进程,替换掉当前进程。即程序不会再返回到原进程,
除非exec调用失败。
exec启动的新进程继承了原进程的许多特性,如在原进程中打开的文件描述符在新进程中仍保持打开。
需要注意的是,在原进程中打开的文件流在新进程中将关闭。原因在于,我们在前面讲过进程间通信的方式,进程之间需要管道才能通信。
原型:
int execl(const char *path,const char *arg0,...,(char*)0); int execlp(const char *file,const char *arg0,...,(char*)0); int execle(const char *path,const char *arg0,...,(char*)0,char *const envp[]); int execv(cosnt char *path,char *const argv[]); int execvp(cosnt char *file,char *const argv[]); int execve(cosnt char *path,char *const argv[],char *const envp[]);
path/file:进程命令路径/进程命令名
argc:命令参数列表
envp:新进程的环境变量
代码示例如下:
process_exec.c
#include<stdio.h> int main() { printf("Running ps with execlp\n"); execlp("ps","ps","au",(char*)0); printf("ps done"); exit(0); }
输出结果:
可以看出,调用execlp函数后,原进程被新进程替换,原进程中printf("ps done");没有被执行到。
3.fork函数-复制进程映像
1)fork函数的使用
fork和exec的替换不同,调用fork函数,可复制一个和父进程一模一样的子进程。
执行的代码也完全相同,但子进程有自己的数据空间,环境和文件描述符。
原型:
pid_t fork();
父进程执行时,返回子进程的PID
子进程执行时,返回0
代码示例如下:
process_fork.c
#include<stdio.h> #include<sys/types.h> int main() { pid_t pid = fork(); switch(pid) { case -1: perror("fork failed"); exit(1); break; case 0: printf("\n"); execlp("ps","ps","au",0); break; default: printf("parent,ps done\n"); break; } exit(0); }
输出结果:
调用fork函数后,新建了一个子进程,拷贝父进程的代码,数据等到子进程的内存空间。父进程和子进程执行互不影响。使用fork函数的返回值,来区分执行的是父进程,还是子进程。
2)僵尸进程
子进程退出后,内核会将子进程置为僵尸状态。此时,子进程只保留了最小的一些内核数据结构,如退出码,以便父进程查询子进程的退出状态。这时,子进程就是一个僵尸进程。
在父进程中调用wait或waitpid函数,查询子进程的退出状态,可以避免僵尸进程。
原型:
pid_t wait(int *stat_loc); pid_t waitpid(pid_t pid,int *stat_loc,int options);
stat_loc:若不是空指针,则子进程的状态码会被写入该指针指向的位置。
pid:等待的子进程的进程号pid
options:标记阻塞或非阻塞模式
返回值:成功返回子进程的pid,若子进程没有结束或意外终止,返回0
wait:阻塞模式(使用了信号量),父进程调用wait时,会暂停执行,等待子进程的结束。
wait调用返回后,子进程会彻底销毁。
waitpid:与wait不同的是,
a.可以表示四种不同的子进程类型
pid==-1 等待任何一个子进程,此时waitpid的作用与wait相同
pid >0 等待进程ID与pid值相同的子进程
pid==0 等待与调用者进程组ID相同的任意子进程
pid<-1 等待进程组ID与pid绝对值相等的任意子进程
b.当options的值为WNOHANG时,为非阻塞模式,即waitpid会立即返回
此时,可以循环查询子进程的状态,若子进程未结束,waitpid返回,做其他工作。
这样提高了程序的效率。
wait函数使用示例如下:
process_fork3.c
#include<wait.h> #include<stdio.h> #include<sys/types.h> int main() { pid_t pid = fork(); int stat = 0; switch(pid) { case -1: perror("fork failed"); exit(1); break; case 0: printf("\n"); exit(0); break; default: pid = wait(&stat); printf("Child has finished:PID=%d\n",pid); printf("parent,ps done\n"); break; } exit(0); }
输出结果:
waitpid函数使用示例如下:
process_fork2.c
#include<wait.h> #include<stdio.h> #include<sys/types.h> int main() { pid_t pid = fork(); int stat = 0; switch(pid) { case -1: perror("fork failed"); exit(1); break; case 0: printf("\n"); execlp("ps","ps","au",0); break; default: do { pid = waitpid(pid,&stat,WNOHANG); if(pid==0) { printf("parent do something else.\n"); sleep(1); } }while(pid==0); printf("Child has finished:PID=%d\n",pid); printf("parent,ps done\n"); break; } exit(0); }
输出结果:
4.启动新进程三种方法的比较
1)system函数最简单,启动shell进程,并在shell进程中执行新的进程。
效率不高,system函数必须等待子进程返回才能接着执行。
2)exec系列函数用新进程替换掉原进程,但不会返回到原进程,除非调用失败。
该函数继承了许多原进程的特性,效率也较高。
3)fork函数,复制一个子进程,和父进程一模一样,但是拥有自己的内存空间。父子进程执行互不影响。需要注意僵尸子进程的问题。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]