sophia0405

当你跌到谷底时,那正表示,你只能往上,不能往下!

 

进程篇之进程初识 -- 内核2.6.11

 本文章,先谈论进程的静态特性,然后再讲内核如何进行进程切换,最后说说如何创建和撤销进程。

       一. Linux源代码中,常把进程称作任务(task)或线程(thread)。

      OS教科书中给进程的定义是:进程是程序执行时的一个实例。 从内核的观点来看,进程的目的就是担当分配系统资源(cpu时间,内存等)的实体。

     当一个进程创建时,它几乎与父进程相同。它接收父进程地址空间的一个(逻辑)拷贝。尽管父子进程可以共享含有程序代码(正文)的页,但是它们各自有独立的数据拷贝(栈和堆),因此子进程对于一个内存单元的修改对父进程是不可见的(反之亦然)。

     下面举个例子来说明:

#include <unistd.h>
#include <stdio.h>
int main(void)
{
 pid_t pid;
 int count=0;
 pid = fork();
 
 printf( "Now, the pid returned by calling fork() is %d"n", pid );
 
 if ( pid>0 )
 {
  printf( "This is the parent process,the child has the pid:%d"n", pid );
  printf( "In the parent process,count = %d"n", count );
 }
 else if ( !pid )
 {
  printf( "This is the child process."n");
  printf( "Do your own things here."n" );
  count ++;
  printf( "In the child process, count = %d"n", count );
 }
 else
 {
  printf( "fork failed."n" );
 }
 
 return 0;
}

 

[root@localhost src]# gcc fork.c

 

[root@localhost src]# ./a.out

Now, the pid returned by calling fork() is 0

This is the child process.

Do your own things here.

In the child process, count = 1

Now, the pid returned by calling fork() is 4139

This is the parent process,the child has the pid:4139

In the parent process,count = 0

 

[root@localhost src]#

 

fork创建的新进程叫做自进程。fork函数被调用一次,却两次返回。返回值唯一的区别是在子进程中返回0,而在父进程中返回子进程的pid。在父进程中要返回子进程的pid的原因是父进程可能有不止一个子进程,而一个进程又没有任何函数可以得到他的子进程的pid

 

子进程和父进程都执行在fork函数调用之后的代码,子进程是父进程的一个拷贝。例如,父进程的数据空间、堆栈空间都会给子进程一个拷贝,而不是共享这些内存。

 

我们来给出详细的注释:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
 pid_t pid;
 int count=0;
 /*此处,执行fork调用,创建了一个新的进程,
 这个进程共享父进程的数据和堆栈空间等,这之后的代码指令为子进程创建了一个拷贝。
 fock 调用是一个复制进程,fock 不象线程需提供一个函数做为入口,
 fock调用后,新进程的入口就在 fock的下一条语句。*/

 pid = fork();
 
 /*此处的pid的值,可以说明fork调用后,目前执行的是那父进程还是子进程*/
 printf( "Now, the pid returned by calling fork() is %d\n", pid );
 
 if ( pid>0 )
 {
  /*当fork在子进程中返回后,fork调用又向父进程中返回子进程的pid,
  如是该段代码被执行,但是注意的事,count仍然为0,
  因为父进程中的count始终没有被重新赋值,
  这里就可以看出子进程的数据和堆栈空间和父进程是独立的,而不是共享数据*/

  printf( "This is the parent process,the child has the pid:%d\n", pid );
  printf( "In the parent process,count = %d\n", count );
 }
 else if ( !pid )
 { /*在子进程中对count进行自加1的操作,但是并没有影响到父进程中的count值,父进程中的count
值仍然为0*/

  printf( "This is the child process.\n");
  printf( "Do your own things here.\n" );
  count++;
  printf( "In the child process, count = %d\n", count );
 }
 else
 {
  printf( "fork failed.\n" );
 }
 
 return 0;
}

    

     Linux使用轻量级的进程( lightweight  processes)。两个轻量级进程基本上可以共享一些资源,诸如地址空间,打开的文件等等。只要其中一个修改共享资源,另一个就可以立即查看这种修改。当然,当2个线程访问共享资源时,就必须同步它们自己。(同步,在以后章节应该是重头戏,呵呵。最近学了不少的同步机制。)

     

 二.进程描述符(Process Descriptor)

          为了管理进程,内核必须对每个进程所做的事情进程清楚的描述。例如,内核必须知道进程的优先级,它是正在cpu上运行还是由于某些事件而被阻塞,给它分配了什么样的地址空间,允许它访问哪个文件等等。这就是进程描述符----进程描述符是task_struct类型结构,它的字段包含了与一个进程相关的所有信息。它不仅包含了进程许多属性的字段,还包含了一些指向其他数据结构的指针。如下图(图片是从 understanding the linux kernel 英文版3 中截取的)  

 

   

               图片中右边的6个数据结构,涉及到进程所拥有的特殊资源。这些资源以后慢慢谈
  


      

posted on 2008-12-30 17:08  土猫敢死队  阅读(263)  评论(0编辑  收藏  举报

导航