有个地方:程序结束后,返回到command中
这里没有讲好,是这样的,程序结束后,CS:IP指向command.com进入用户程序前的下一条语句(最后一条语句是“然后设置CPU的CS:IP指向程序的第一条指令”)
此时,command.com从stack里弹出(pop)2或4字节的内容,这些内容就是用户程序的返回值。
没有返回值就是0,所以编写正常的main就算是void型的也可以照常退回dos。
再好好修改扩展一下,写好点加精。
现在就能加精了
抱膝怀天下 闲坐观四海
子曾经曰过:源码在前,了无秘密.
我15楼已经给出了一个简单的shell实现,不过只是分析了执行程序时进程的活动,main函数的调用和返回没有详细说,现在尽我所知尽可能的说详细些,以UNIX系统为例:
当系统执行c程序时是通过一个exec调用,在这个调用中进入main之前还有个特殊的启动routine,该routine是进程中程序的入口地址,工作是从OS内核中取得命令行参数和环境变量,打开stdin,sdtout,stderr三个文件流,为进入main做准备。之后的工作就是调用main了,main返回之后该进程立即调用exit函数,将main的返回值传递到OS内核。由于该routine通常用汇编写,这里给出等价的c代码:exit(main(argc,argv));exit函数会执行标准IO库的清理关闭操作:为所有打开流调用fclose函数,让所有缓冲的数据都被冲洗,写到文件中。
exit使用一个整形参数(shell提供从内核获取该值的功能),若main执行一个无返回值的return语句或main没有声明返回值为整形,该进程的终止状态是未定义的,但若main的返回值声明为整形但执行到最后一句时没有显式的return或exit()一个整数,那么该进程的终止状态是0。这种处理是C99规定的,C99标准之前没有显式返回的进程的终止状态也是未定义的。见下例:
#include<stdio.h>
main()
{
printf(\"hello.world\n\");
}
$ cc hello.c
$ ./a.out
hello,world
$ echo $?
13
$ cc -std=c99 hello.c
hello.c:c4:warning:return type defaults to 'int'
$ ./a.out
hello,world
$ echo $?
0
上面几段差不多说清了main的一生一世,进入到退出,不过还是比较杂乱,看的让人有点头晕,那个简易的shell模型启动应用程序的过程中执行流程在用户态和内核态之间来回穿梭,下面给个图说明:
用户态 【shell】----- --【新的shell进程】-- --【执行main的进程】--
↓fork ↑ ↓exec ↑ ↓return或exit调用
------------------------------------------------------------------------------------------------------------------
↓ ↑ ↓ ↑ ↓
内核态 内核fork服务------- 内核exec服务----- 获取终止码撤销进程服务
OVER,以我目前的功力只能分析到这一层了,我师弟已于前日退出论坛,我在这里也没意思,回去闭关修炼去也。
PS:那些个不学无术的最好找个CS的本科专业认真念四年,不才在CS&T专业混了四年才把一只脚伸进CS的大门。还有那个叫栖柏的小P孩不要再灌水了,回去老实念书去。
================================================================================================================
Bibliography
Addison Wesley,Advanced Programming in the UNIX Environment: Second Edition
By W. Richard Stevens, Stephen A. Rago
Person Education,Modern Operating Systems:Second Edition
By Andrew S.Tanenbaum