Linux 多进程通信开发(一):fork 进程

这会是一系列文章,文章的目的是让自己的知识固话和文档化,以备自己不时的复习,同时也希望能够给予初学者一些帮助。

进程是操作系统中一个很重要的概念,几乎每一种应用都是单独跑在一个进程当中。

我们编译生成的程序一般放在磁盘上,需要运行的时候内核会创建一个进程空间,分配内存,然后分配 ID 号码,再将程序的代码段存放在一个地方,程序中定义的静态变量和全局变量存放在一个地方,动态分配的内存划定在进程的堆,函数的调用存放在进程空间的栈。程序能够运行,可以看做是内核不停地读取进程空间里的代码和数据,并且不同进程内存独立,所以代码独立,不会互相干扰

除了操作系统内核能够为程序分配进程外,程序自己也能够创建子进程。

本文讲解 Linux 下怎么创建进程,示例代码用 C++ 编写。

创建进程需要用到 fork() 这个 API。

extern __pid_t fork (void) __THROWNL;
1
它定义在 unistd.h 这个头文件中。

fork 返回的数值是代表进程的 ID。

每个进程都有一个 ID,我们一般叫做 pid。

自己的进程和父进程都可以通过 API 获取到。

/* Get the process ID of the calling process. */
extern __pid_t getpid (void) __THROW;

/* Get the process ID of the calling process’s parent. */
extern __pid_t getppid (void) __THROW;

getpid() 会返回自身进程的 pid
getppid() 会返回父进程的 pid

fork() 会执行两次
前面讲到 fork() 会创建一个进程。

但是有个很重要的地方就是,创建后的子进程会完全复制父进程的资源,文章开始就有写过,程序的代码会保存在进程的一块区域,所以在 fork() 发生之前的父子进程的代码是一模一样,然后也会同样往下执行。

那么怎么分辨它们呢?

通过 pid

因为父子进程代码一模一样,所以子进程也可以得到 fork() 的结果,但是它得到的是 0.

父进程得到 fork() 返回来的是子进程的 pid。

如果 fork() 返回 -1,表示创建子进程出错了。

正因为父子进程得到 fork 的 pid 不一样,所以通过 pid 就可以很轻易分辨父子进程了。

下面是示例代码。

#include <unistd.h>
#include

using namespace std;

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

pid_t pid = fork();

switch (pid)
{
    case -1:
        cerr << "Fork is faild!" << endl;

        break;

    case 0:
        cout << "I\'m child process ,pid is " << getpid() << " parent process is " << getppid() << endl;
        break;

    default:
        cout << "I\'m father process,pid is  " << getpid() << "child pid is " << pid << endl;
        sleep(3);
        break;
}

return 0;

}

代码是 C++ 写的,如果不习惯用 C,也是可以的。

编译后执行 a.out,结果如下。

I’m father process,pid is 10447child pid is 10448
I’m child process ,pid is 10448 parent process is 10447

上面的代码示范了如何区别父子进程。

真实开发中,fork 出来的子进程一般会执行 exec 方法,调用其它的应用程序,这就是它的使命。

父子进程的执行顺序
这个是不一定的,有可能子进程先运行,也有可能父进程先运行。

父进程在子进程前面结束,子进程将失去父亲称为一个孤儿进程,被托孤给 init 进程,很多应用利用这点创建守护进程。

vfork
vfork 也可以创建新线程,但是有一点点不一样。

fork 后的进程完全复制了父进程的资源,所以它的资源是独立的,因此开销比较大。

前面说过 fork 后一般会调用 exec ,然后自己就结束了,所以比较浪费。

而 vfork 是共享父进程的资源,它改了什么,父进程会跟着受影响,但它减少了开销,因为它不需要将父进程的资源重新拷贝一份。

并且,vfork 后子进程先运行,父进程阻塞,直到子进程结束.

猜你喜欢

转载自blog.csdn.net/Hql_ztz/article/details/89349046
今日推荐