zoukankan      html  css  js  c++  java
  • Linux学习--进程创建

    进程创建

    在Linux系统下,自己可以创建进程:

       当进程执行时,它会被装载进虚拟内存,为程序变量分配空间,并把相关信息添到 task_struct里。

    进程内存布局分为四个不同的段: 

    • 文本段,包含程序的源指令。 

    • 数据段,包含了静态变量。 

    • 堆,动态内存分区区域。 

    • 栈,动态增长与收缩的段,保存本地变量。 

    下面来说进程的创建方法:

    一:fork:

    1.函数原型:

    pid_t fork( void);  
    2.返回值:

    若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1

    3.举例:

    4.fork函数说明:

    一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。UNIX将复制父进程的地址空间内容给子进程,因此,子进程有了独立的地址空间。在不同的UNIX (Like)系统下,我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的实现。

    二,vfork:

    1.函数原型:

    pid_t vfork(void) ;   //头文件 #include<unistd.h>

    2.返回值:

    如果vfork()成功则在父进程会返回新建立的子进程代码(PID),而在新建立的子进程中则返回0。如果vfork失败则直接返回-1;

    3.例子:

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<wait.h>
     
    int main(void)
    {
        pid_tpid;
        if((pid=vfork())<0)
    	{
    		perror("vforkisfailed");
    		exit(1);
    	}
    	elseif(pid==0)
    	{
    		printf("thisischildprocess
    ");
    		exit(0);
    	}
    	else
    	{
    		printf("thisisparentprocess
    ");
    		if(wait(NULL)==-1)
    		{
    			perror("failtowait");
    			exit(1);
    		}
    	}
    	return0;
    }
    以上为两种常用的进程创建函数。

    关于fork和vfork的却别:

    1. fork():子进程拷贝父进程的数据段,代码段. vfork():子进程与父进程共享数据段.

    2. fork():父子进程的执行次序不确定. vfork():保证子进程先运行,在调用exec或_exit之前与父进程数据是共享的,在它调用exec或_exit之后父进程才可能被调度运行。

    3. vfork()保证子进程先运行,在她调用exec或_exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

    4.当需要改变共享数据段中变量的值,则拷贝父进程。

    vfork函数的说明:

            vfork用于创建一个新进程,而该新进程的目的是exec一个新进程,vfork和fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,不会复制页

    表。因为子进程会立即调用exec,于是也就不会存放该地址空间。不过在子进程中调用exec或exit之前,他在父进程的空间中运行。

            为什么会有vfork,因为以前的fork当它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,而往往在子进程中会执行exec调用,这样,前面的拷贝工

    作就是白费力气了,这种情况下,聪明的人就想出了vfork,它产生的子进程刚开始暂时与父进程共享地址空间(其实就是线程的概念了),因为这时候子进程在父进程的地址

    空间中运行,所以子进程不能进行写操作,并且在儿子“霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec或者exit后,相当于儿子

    买了自己的房子了,这时候就相当于分家了。

            vfork和fork之间的另一个区别是: vfork保证子进程先运行,在她调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动

    作,则会导致死锁。由此可见,这个系统调用是用来启动一个新的应用程序。其次,子进程在vfork()返回后直接运行在父进程的栈空间,并使用父进程的内存和数据。这意味着

    子进程可能破坏父进程的数据结构或栈,造成失败。

            为了避免这些问题,需要确保一旦调用vfork(),子进程就不从当前的栈框架中返回,并且如果子进程改变了父进程的数据结构就不能调用exit函数。子进程还必须避免改变

    全局数据结构或全局变量中的任何信息,因为这些改变都有可能使父进程不能继续。通常,如果应用程序不是在fork()之后立即调用exec(),就有必要在fork()被替换成vfork()之

    前做仔细的检查。

            用vfork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序,当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其main函数开始执

    行,因为调用exec并不创建新进程,所以前后的进程id 并未改变,exec只是用另一个新程序替换了当前进程的正文,数据,堆和栈段。

    主要为理解,概念性东西随处可见!

    赐教!

  • 相关阅读:
    poj 1789 每个字符串不同的字母数代表两个结点间的权值 (MST)
    poj 1251 poj 1258 hdu 1863 poj 1287 poj 2421 hdu 1233 最小生成树模板题
    poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)
    hdu 5256 最少修改多少个数 能使原数列严格递增 (LIS)
    hdu 1025 上面n个点与下面n个点对应连线 求最多能连有多少条不相交的线 (LIS)
    Gym 100512F Funny Game (博弈+数论)
    UVa 12714 Two Points Revisited (水题,计算几何)
    UVa 12717 Fiasco (BFS模拟)
    UVa 12718 Dromicpalin Substrings (暴力)
    UVa 12716 && UVaLive 6657 GCD XOR (数论)
  • 原文地址:https://www.cnblogs.com/melons/p/5791805.html
Copyright © 2011-2022 走看看