linux 进程函数,深入解读Linux进程函数fork(),vfork(),execX()

本文研究的主要是Linux进程函数fork(),vfork(),execX()的相关内容,具体介绍如下。

函数fork()

fork函数:创建一个新进程

1、fork()成功后,将为子进程申请PCB和用户内存空间。

2、子进程会复制父进程用户空间的所有数据(代码段、数据段、BSS、堆、栈),文件描述符。

3、复制父亲进程PCB中绝大多数信息。

4、虽然子进程复制了文件描述符,而对于文件描述符相关的文件表项(struct file结构),则采用共享的方式。

一个实例:

#include //fork fuction

#include //file operator

#include

#include

#include //exit fuction

#include

int main() {

pid_t pid;

int i=1;

int status;

char *ch1="hello",*ch2="world",*ch3="IN";

int fd;

if ((fd=open("fork.txt",O_RDWR|O_CREAT,0644))==-1) {

perror("not open");

exit(EXIT_FAILURE);

}

if (write(fd,ch1,strlen(ch1))==-1) { //write in fork.txt

perror("not write");

exit(EXIT_FAILURE);

}

if ((pid=fork())==-1) {

perror("fork error");

exit(EXIT_FAILURE);

}

else if(pid==0) { //son process

int i=2; //change i

printf("child:i=%d\n",i);

if (write(fd,ch2,strlen(ch2))==-1)

perror("child write");

return 0;

}

else {

sleep(1);

printf("parent:i=%d\n",i);

if (write(fd,ch3,strlen(ch3))==-1)

perror("child write");

wait(&status);

return 0;

}

}

运行:

[root@localhost linux]# gcc -o fork fork.c

[root@localhost linux]# ./fork

child:i=2

parent:i=1

可以看到在子进程中改变了i的值,然而父进程i仍为1,所以说子进程和父进程有自己的用户空间。而打开所创建的fork.txt可以得到hellowordIN,父子进程共同对一个文件操作写入的数据是不交叉覆盖的,说明父子进程共享文件偏移,一次共享文件表项。

函数vfork()

与fork()函数不同,vfork()函数在创建进程是并不复制父进程的地址空间,而是在必要的时候才申请新的存储空间,因此使得vfork()更有效率。

特别注意的是vfork()是共享父进程的代码以数据段。

一个例子:

#include //fork fuction

#include //file operator

#include

#include

#include //exit fuction

#include

int i=10;

int main() {

pid_t pid;

if ((pid=fork())==-1) {

perror("fork error");

exit(EXIT_FAILURE);

}

else if(pid==0) { //son process

i++;

printf("child:i=%d\n",i);

_exit(0);

}

else {

sleep(1);

printf("parent:i=%d\n",i);

return 0;

}

}

注意:上面的代码中回收子进程用的是_exit(0),如果用return 0;的话它会回收用户空间,因此在父进程调用的时候会出现段错误。

下面是调用输出结果:

如果以fork()创建则会输出:

[root@localhost linux]# ./fork

child:i=11

parent:i=10

如果改为vfork(),则:

child:i=11

parent:i=11

函数exec X()系列函数

用fork()函数创建紫禁城后,如果希望在当前子进程中运行新的程序,则可以调用execX系列函数。

注意:当进程调用exec函数后,该进程的用户空间资源完全有新程序代替。

这些函数的区别在于:

1、指示新程序的位置是路径还是文件名

2、在使用参数时是使用参数列表哈市使用argv[]数组

3、后缀有l(list)表示使用参数列表,v表示使用argv[]数组

具体如下所示:

#include

int execl(const char *pathname,const char *arg0,.../*(char *) 0 */);

int execv(const char *pathname,char *const argv[]);

int execle(const char *pathname,const char *arg0,.../*(char *) 0

,char *const envp[] */);

int execve(const char *pathname,char *const argv[],char *const envp[]);

int execlp(const char *filename,const char*arg0,.../*(char *) 0*/);

int execvp(const char *filename, char *const argv[]);

int fexecve(int fd,char *const argv[],char *const evnp[]);

一个实例:

#include

#include

#include

int main(int argc ,char* argv[]) {

pid_t pid;

if ((pid=fork())==-1)

printf("error");

else if (pid==0)

execl("/bin/ls","ls","-l",argv[1],(char *)0);

else

printf("father ok\n");

}

运行可以看到在子进程中执行了ls命令。

[yqtao@localhost linux]$ gcc -o exec execX.c

[yqtao@localhost linux]$ ./exec /home father ok

//execlp()函数使用

#include

#include

#include

int main(int argc ,char* argv[]) {

execlp("ls","ls","-l","/home",(char*)0);

}

//execv()函数的使用

#include

#include

#include

int main(int argc ,char* argv[]) {

char* argv1[]={"ls","-l","/home",0};

execv("/bin/ls",argv1);

}

ecvp()会从环境变量PATH所指定的目录中查找文件名作为第一个参数,第二个及以后的参数由参数列表,注意最后一个成员必须为NULL

#include

#include

#include

int main(int argc ,char* argv[]) {

char* argv1[]={"ls","-l","/home",0};

execvp("ls",argv1);

}

总结

以上就是本文关于深入解读Linux进程函数fork(),vfork(),execX()的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值