第一章 环境
Ubuntu 14.10
Linux 3.18.6
第二章 源代码
转自:http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html
并进行过修改。
C
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main ()
{
pid_t fpid;
int count=0;
fpid=fork();
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0)
{
printf("I am the child process, my process id is %d\n",getpid());
count++;
}
else
{
printf("I am the parent process, my process id is %d\n",getpid());
count++;
}
printf("Result is: %d\n",count);
return 0;
}
AT&T
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main ()
{
pid_t fpid;
int count=0;
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x2,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(fpid)
);
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0)
{
printf("I am the child process, my process id is %d\n",getpid());
count++;
}
else
{
printf("I am the parent process, my process id is %d\n",getpid());
count++;
}
printf("Result is: %d\n",count);
return 0;
}
在编译的时候提示:
fork_call.c: Assembler messages:
fork_call.c:10: Error: operand size mismatch for `int'
fork_call.c:11: Error: operand type mismatch for `mov'
对比才发现是一些符号的问题,在此检讨,要细心,多分析。
结果:
C
AT&T
下面便是调试了。
第三章 调试
输入以下命令开始调试
$gcc -m32 -g -o fork_call fork_call.c
$gdb fork_call -tui -q
接着先查看源代码
(gdb)layout src
设置断点
(gdb)break main
查看寄存器
(gdb)layout regs
逐条运行
(gdb)si
这里提一下:si的运行取决于layout所看的视图是汇编视图还是源代码视图,汇编视图逐汇编语句运行,源代码视图逐源代码语句运行。
调试截图:
第四章 分析
由调试过程可知:
首先将ebx设置成0,然后将eax设置成2,这样就可以通过syscall_32.tbl进行调用fork()函数运行。然后返回eax返回函数值0xf4b,于是便完成了调度。不过,在将eax设置成2后,有一个段代码:int 0x80。这个的意思是产生中断,这样我们便可以从用户态转换为内核态,从而调用了系统的函数fork()。
第五章 总结
系统是通过中断的方式将用户态转换为内核态,同时调用系统函数来实现系统功能。当系统中断出现时,CPU保护现场和上下文切换来保护目前用户态所运行的状态,并通过返回系统调用函数的值来让用户判断是否已经有效地调用,结果如何。如exit(),waitpid(),getpid(),fork(),sysinfo()等等。这些方式就是系统级应用程序接口对用户系统编程提供的帮助,使用户更好地管理内核。
下面是一篇博文对int 0x80的解析:(http://blog.csdn.net/u010467259/article/details/40130599)
软中断实现过程:
第六章 拓展
汇编调用getpid()函数。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
pid_t fpid;
int ret=0;
int count=0;
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x2,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(fpid)
);
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0)
{
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x14,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(ret)
);
printf("I am the child process, my process id is %d\n",ret);
count++;
}
else
{
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x14,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(ret)
);
printf("I am the parent process, my process id is %d\n",ret);
count++;
}
printf("Result is: %d\n",count);
return 0;
}
汇编调用open(char *,char *)函数
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
FILE *file=NULL;
char *filename="1.txt";
char *r="r";
asm volatile(
"mov $0,%%ebx\n\t"
"mov %1,%%ebx\n\t"
"mov %2,%%ecx\n\t"
"mov $0x5,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(file)
:"b"(filename),"c"(r)
);
return 0;
}
附录
卢晅 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000