UNIX进程环境小结

       今天又看了UNIX进程环境一章,主要讲当执行程序时,其main函数是如何被调用的,命令行参数是如何传送给执行程序的;典型的存储器布局是什么样等,对于理解进程如何执行很是有用,一定要记下来。

       先看看main函数是如果被调用,又如何退出的(以前一直以为main就是一个程序的一生了,实在是糊涂啊L)。先看下图:

 

       一个进程的生死就是这样的了。

       C程序总是从main函数开始执行。标准main函数的原型是:

int main ( int argc, char *argv[ ] ) ;

       当内核起动C程序时使用一个exec函数在调用main前先调用一个特殊的起动例程。可执行程序文件将此起动例程指定为程序的起始地址——这是由link程序设置的,而link程序则由C编译程序(例如gcc)调用。起动例程从内核取得命令行参数和环境变量值,传入main函数然后开始用户程序的执行。当从main函数返回后,(正常情况下)起动例程调用exit终止进程,回到内核。这个过程是通常的处理流程。但也不一定必须这样,比如可以在main中调用exitreturn),这是更普遍的写法。

       注:上图中exit_exit都是正常终止进程。但exit要处理一系列清理工作,如调用执行各终止处理程序,关闭所有标准I/O流等,_exit是直接返回内核。

       强调一下的是:

       内核使程序执行的唯一方法是调用一个exec函数。进程自愿终止的唯一方法是显式或隐式地(调用exit)调用_exit

      

命令行参数如何被传送给用户进程?

这个比较简单,当执行一个程序时,调用exec的进程可将命令行参数传递给该程序,例如shellargc是参数的个数,argv是指向参数组的指针。只需要注意一点,argv[argc]一定是空指针,它表示结束。

 

C程序在内存空间中的典型布局:

TEXT(正文段):是由CPU执行的机器指令部分,通常是只读、可共享的。可共享是为了让经常执行的程序在内存中只有一个副本,只读是为了防止被修改。

初始化数据段:存放已经有初始值的全局变量、静态变量。

未初始化数据段(BSS):存放仅仅声明了而没有被初始化的全局变量,但程序执行前,由exec赋初值0

堆(heap):用于动态内存分配,其长度不定。

栈(stack):用于局部变量以及函数调用切换时的环境信息保存,其长度不定。

从图中还可以看到,未初始化数据段的内容并不存放在磁盘程序文件中。需要存放在磁盘程序文件中的段只有正文段和初始化数据段。也就是我们常说的,声明一个变量不分配空间,只有定义了变量才会分配空间。

shell下用size命令报告正文段、数据段和bss段的长度。

 

题外话:

上次在csdn的论坛看到某公司的面试题:能否在main函数执行完后再执行一些其它操作?有人回答用atexit可以,当时看了并查了msdn,对于atexit的解释如下:

int atexit( void ( __cdecl *func )( void ) );

Processes the specified function at exit.

The atexit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to atexit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to atexit cannot take parameters.

Example:

void fn1( void ), fn2( void ), fn3( void ), fn4( void );

 

void main( void )

{

   atexit( fn1 );

   atexit( fn2 );

   atexit( fn3 );

   atexit( fn4 );

   printf( "This is executed first./n" );

}

 

void fn1()

{

   printf( "next./n" );

}

 

void fn2()

{

   printf( "executed " );

}

 

void fn3()

{

   printf( "is " );

}

 

void fn4()

{

   printf( "This " );

}

 

Output:

This is executed first.

This is executed next.

 

当时看了msdn也只是接受了这个函数,并不明白来龙去脉。今天了解了C程序的调用过程,才明白了真正的原理,atexit只是注册一些函数(这些函数可以叫作“exit handler”,这些函数将由exit在终止进程前调用。atexitANSI C支持,早期的一些系统不一定支持。

 

Ok,今天就到这里,休息了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值