Linux系列

  进程 (Process)是指操作系统中被加载到内存中的、正在运行的应用程序实例。进程是系统资源分配的基本单元,在其生命周期内会使用系统中的各种资源。进程主要由程序、数据以及进程控制快(PCB)3个部分组成。关于其基本知识和其状态相关的知识就不介绍了。下面来看看进程的创建和操作吧。

  当然,Linux系统中创建进程的函数调用很多(如:system()、popen()等等),此处,主要介绍下fork()函数:

/* Clone the calling process, creating an exact copy.
   Return -1 for errors, 0 to the new process,
   and the process ID of the new process to the old process.  */
extern __pid_t fork (void) __THROWNL;

  用户可以通过Linux系统提供的fork()来创建多个子线程一实现多个不同任务的并发执行。若创建成功,则从子线程返回0,从父线程返回大于0的正整数(即子线程的惟一标识符id),否则返回-1,表示创建失败。

  操作系统内核为完成fork()调用执行的有以下操作:(1)为新进程分配一进程表项和进程标识符,操作系统会检查系统是否有足够的资源来建立一个新进程(2)检查同时存在且正在运行的进程数目,若超过预先规定的最大进程数目,fork()系统调用将会失败。(3)拷贝进程表项中的数据,将父进程的当前记录和所有已打开的数据拷贝到子进程表项中,并置进程的状态为“创建”状态。(4)子进程继承父进程的所有文件(5)为子进程创建进程上下文(6)执行子进程,虽然父进程和子进程程序完全相同,但每个进程都有自己的程序计数器PC,并根据fork()返回值的不同,执行不同的分支语言。因此,可以确定fork()是通过复制当前进程来创建新进程的。

#include<stdio.h>
#include<unistd.h>
int main()
{
  int pid;
  pid=fork();
  while(pid==-1);//创建子进程直到成功为止
  if(pid)
    {
      printf("子进程\n");
      sleep(1);
    
    }
  else
    {
      printf("父进程\n");
      sleep(1);
    }return 0;
}

程序运行结果:子进程  或者   父进程

       父进程            子进程

  从进程并发执行来看,2种情况都有可能,因为父子进程没有同步机制,所以父进程与子进程的输出内容会叠加在一起,输出次序带有随机性。

  

下面我们继续对Linux中父子进程对程序的共享与私有部分

(1)父进程创建子进程后,父子进程各自分支中的部分规个自私有,其余部分(包括创建前和分支结束后的程序段)都为父子进程共享。先面看个例子:

#include<stdio.h>
#include<unistd.h>
int main()
{
  int p;
  putchar('X');
  while((p=fork())==-1);
  if(p==0)
    {
      putchar('B');
    }
  else
    putchar('A');
  putchar('Y');
  return 0;
}

运行结果:XAYXBY或XBYXAY

(2)如果子进程在其分支结束处使用exit()系统调用来终止自身的执行,则不会在共享其后的程序段。

(3)对于父子进程不共享的程序段,它们都有各自不同的进程映像,在自己的私有存储空间对数据进行修改不会影响到对方。

#include<stdio.h>
#include<unistd.h>
int main()
{
  int p;
  int x=1;
  while((p=fork())==-1);
  if(p==0)
    {
      x=9;
      printf("child:x=%d\n",x);
    }
  else
    printf("parent:x=%d\n",x);
  return 0;
}

运行结果:child:x=9

     parent:x=1

 

Linux进程树

  如果一个程序中使用了多个fork()调用,而且每次都不对返回值加以判断,不分析父子进程各自的程序空间,则后面的fork()调用为父子进程所共享,即父子进程返回时都会执行,从而使得家族的进程关系变得复杂。

#include<stdio.h>
#include<unistd.h>
int main()
{
  fork();
  fork();
  fork();
  putchar('A');
  return 0;
}

运行结果:AAAAAAAA

家族树图稍后上传。。

  先面我们在进一步看fork()&&fork()||fork():

此处涉及到逻辑运算符运行的机制和对fork()的更深层次了解与认识。其实此式新创建进程4个,下面来分析下:

A&&B 如果A=0,则就没必要执行B了,如果A!=0,则就执行B;

A||B 如果A=0则就执行B,如果A!=0则就不用执行B了。

 

  由此可见fork()&&fork()||fork()创建了4新进程,同理,类此问题迎刃而解。。。

 

posted @ 2016-11-10 17:18  追求沉默者  阅读(925)  评论(0编辑  收藏  举报