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

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

函数fork()

fork函数:创建一个新进程

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

一个实例:

#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;
 }
}

运行:

[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 <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;的话它会回收用户空间,因此在父进程调用的时候会出现段错误。

下面是调用输出结果:

如果以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<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[]);

一个实例:

#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命令。

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

//execlp()函数使用

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

//execv()函数的使用

#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

#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()的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • 详解linux中fork、vfork、clone函数的区别

    在linux系统中,fork(),vfork()和clone函数都可以创建一个进程,但是它们的区别是什么呢???本文就这三者做一个较深入的分析!!! 1.fork() fork()函数的作用是创建一个新进程,由fork创建的进程称为子进程,fork函数调用一次返回两次,子进程返回值为0,父进程返回子进程的进程ID.我们知道,一个进程的地 址空间主要由代码段,数据段,堆和栈构成,那么p2就要复制相关的段到物理内存.原始的unix系统的实现的是一种傻 瓜式的进程创建,这些复制包括: (1) 为子进程

  • 浅谈Linux vfork与fork简单对比分析

    本文分享了Linux vfork与fork简单对比分析,分享给大家,具体如下: fork相关问题: 一.fork基础了解 fork作用为创建一个子进程,在使用了fork命令后,内核会分配新的内存块和数据结构给子进程,并且将父进程的部分数据结构内容拷贝到子进程,最后再将子进程添加到系统进程列表中,添加完成后fork返回,开始调度. 头文件:#include < unistd.h > 函数原型:pid_t fork( ) 返回值:返回值大于0则当前进程为父进程,等于0代表为子进程,小于零代表创建子

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

    本文研究的主要是Linux进程函数fork(),vfork(),execX()的相关内容,具体介绍如下. 函数fork() fork函数:创建一个新进程 1.fork()成功后,将为子进程申请PCB和用户内存空间. 2.子进程会复制父进程用户空间的所有数据(代码段.数据段.BSS.堆.栈),文件描述符. 3.复制父亲进程PCB中绝大多数信息. 4.虽然子进程复制了文件描述符,而对于文件描述符相关的文件表项(struct file结构),则采用共享的方式. 一个实例: #include <unis

  • Linux 进程替换(exec函数)实现代码

    Linux 进程替换(exec函数)实现代码 # include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<sys/types.h> #include<sys/stat.h> #include<string.h> int main() { pid_t id=fork(); if(id==0) { printf(&quo

  • Linux进程基础教程详解

    计算机实际上可以做的事情实质上非常简单,比如计算两个数的和,再比如在内存中寻找到某个地址等等.这些最基础的计算机动作被称为指令 (instruction).所谓的程序(program),就是这样一系列指令的所构成的集合.通过程序,我们可以让计算机完成复杂的操作.程序大多数时候被存储为可执行的文件.这样一个可执行文件就像是一个菜谱,计算机可以按照菜谱作出可口的饭菜. 那么,程序和进程(process)的区别又是什么呢? 进程是程序的一个具体实现.只有食谱没什么用,我们总要按照食谱的指点真正一步步实

  • Linux进程控制详解及实例

    Linux进程控制详解及实例 常用函数: fork() 通过复制调用进程来建立新的进程,是最基本的进程建立操作. exec   包括一系列的系统调用,其中每个系统调用都完成相同的功能,即通过用一个新的程序覆盖原内存空间,来实现进程的转变.各种exec系统调用之间的区别仅在于它们的参数构造不同. wait() 它提供了初级的进程同步措施,能使一个进程等待,直到另一个进程结束为止. exit()  常用来终止一个进程的运行. 进程的建立 如果fork()调用成功,就会使内核建立一个新的进程,所建的新

  • Linux多线程中fork与互斥锁过程示例

    目录 问题提出: (一)初次尝试 (二)理性分析 (三)解决问题 (1)使用pthread_join() (2)使用phread_atfork()注册一个fork之前的判断 问题提出: 我们有这样一个问题:在一个多线程程序中创建子进程并且让子线程和子进程去获取一把全局变量的锁,输出子线程得到锁,然后解锁,子进程拿到锁,然后解锁: (一)初次尝试 代码: #include <stdio.h> #include <unistd.h> #include <pthread.h>

  • Python中的进程分支fork和exec详解

    在python中,任务并发一种方式是通过进程分支来实现的.在linux系统在,通过fork()方法来实现进程分支. 1.fork()调用后会创建一个新的子进程,这个子进程是原父进程的副本.子进程可以独立父进程外运行. 2.fork()是一个很特殊的方法,一次调用,两次返回. 3.fork()它会返回2个值,一个值为0,表示在子进程返回;另外一个值为非0,表示在父进程中返回子进程ID. 以下只能在linux中运行,不能在window下运行. 进程分支fork() 实例如下: 复制代码 代码如下:

  • 详细解读linux下swap分区的作用

    本文研究的主要是linux下swap分区的相关内容,具体介绍如下. swap分区介绍 嵌入式Linux中文站消息,Linux系统的Swap分区,即交换区,Swap空间的作用可简单描述为:当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用.那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap中恢复保存的数据到内存中.这样,系统总是在物理内存不够时,才进行Swap交换.其实,S

  • Linux unlink函数和删除文件的操作方法

    1. unlink函数   对于硬链接来说,unlink 用来删除目录项,并把 inode 引用计数减 1,这两步也是一个原子过程.直到 inode 引用计数为 0,才会真正删除文件.   对于软链接来说,unlink 直接删除软链接,而不影响软链接指向的文件. 函数原型: int unlink(const char *pathname);   参数说明:   pathname:指定要移除的链接文件 返回值说明:   成功返回0:失败则返回-1,同时设置errno为相应值 2. 实验代码-myu

  • 6种查看Linux进程占用端口号的方法详解

    对于 Linux 系统管理员来说,清楚某个服务是否正确地绑定或监听某个端口,是至关重要的.如果你需要处理端口相关的问题,这篇文章可能会对你有用. 端口是 Linux 系统上特定进程之间逻辑连接的标识,包括物理端口和软件端口.由于 Linux 操作系统是一个软件,因此本文只讨论软件端口.软件端口始终与主机的 IP 地址和相关的通信协议相关联,因此端口常用于区分应用程序.大部分涉及到网络的服务都必须打开一个套接字来监听传入的网络请求,而每个服务都使用一个独立的套接字. 套接字是和 IP 地址.软件端

  • linux stat函数讲解(整理)

    stat函数讲解 表头文件: #include <sys/stat.h> #include <unistd.h> 定义函数: int stat(const char *file_name, struct stat *buf); 函数说明: 通过文件名filename获取文件信息,并保存在buf所指的结构体stat中 返回值: 执行成功则返回0,失败返回-1,错误代码存于errno 错误代码: ENOENT         参数file_name指定的文件不存在     ENOTDI

随机推荐