gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 39 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章深入解读Linux进程函数fork(),vfork(),execX()由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

函数fork()

fork函数:创建一个新进程 。

1、fork()成功后,将为子进程申请PCB和用户内存空间。
2、子进程会复制父进程用户空间的所有数据(代码段、数据段、BSS、堆、栈),文件描述符。
3、复制父亲进程PCB中绝大多数信息。
4、虽然子进程复制了文件描述符,而对于文件描述符相关的文件表项(struct file结构),则采用共享的方式。

一个实例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <unistd.h> //fork fuction
#include <fcntl.h> //file operator
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h> //exit fuction
#include <string.h>
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;
  }
}

运行:

?
1
2
3
4
[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()是共享父进程的代码以数据段.

一个例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <unistd.h> //fork fuction
#include <fcntl.h> //file operator
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h> //exit fuction
#include <string.h>
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;的话它会回收用户空间,因此在父进程调用的时候会出现段错误.

下面是调用输出结果:

?
1
2
3
4
5
6
7
如果以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[]数组 。

具体如下所示:

?
1
2
3
4
5
6
7
8
9
10
#include<unistd.h>
 
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[]);

一个实例:

?
1
2
3
4
5
6
7
8
9
10
11
12
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
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命令.

?
1
2
[yqtao@localhost linux]$ gcc -o exec execX.c
[yqtao@localhost linux]$ ./exec /home father ok

//execlp()函数使用 。

?
1
2
3
4
5
6
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
int main( int argc , char * argv[]) {
  execlp( "ls" , "ls" , "-l" , "/home" ,( char *)0);
}

//execv()函数的使用 。

?
1
2
3
4
5
6
7
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
int main( int argc , char * argv[]) {
  char * argv1[]={ "ls" , "-l" , "/home" ,0};
  execv( "/bin/ls" ,argv1);
}

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

?
1
2
3
4
5
6
7
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
int main( int argc , char * argv[]) {
  char * argv1[]={ "ls" , "-l" , "/home" ,0};
  execvp( "ls" ,argv1);
}

总结

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

原文链接:http://blog.csdn.net/taoyanqi8932/article/details/52778015 。

最后此篇关于深入解读Linux进程函数fork(),vfork(),execX()的文章就讲到这里了,如果你想了解更多关于深入解读Linux进程函数fork(),vfork(),execX()的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com