《Linux内核分析》之触发一个系统调用实验总结

前言

系统调用列表中可用的很多,可惜对用代码进行系统调用不太清楚,只好从网上窃取了一份,地址在最后放上。此处以fork()为例。

实验及代码

fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值: 1)在父进程中,fork返回新创建子进程的进程ID; 2)在子进程中,fork返回0; 3)如果出现错误,fork返回一个负值;

使用库函数API调用

使用库函数API

代码

#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 %dn",getpid());
        count++;
    }
    else
    {
        printf("I am the parent process, my process id is %dn",getpid());
        count++;
    }
    printf("Result is: %dn",count);
    return 0;
}

 效果图

使用C代码中嵌入汇编代码调用

使用C代码中嵌入汇编代码调用

代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main ()
{
    pid_t fpid;
    int count=0;
    asm volatile(
        "mov $0,%%ebxnt"
        "mov $0x2,%%eaxnt"
        "int $0x80nt"
        "mov %%eax,%0nt"
        :"=m"(fpid)
    );
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0)
    {
        printf("I am the child process, my process id is %dn",getpid());
        count++;
    }
    else
    {
        printf("I am the parent process, my process id is %dn",getpid());
        count++;
    }
    printf("Result is: %dn",count);
    return 0;
}

 效果图

使用C代码中嵌入汇编代码实验测试

使用C代码中嵌入汇编代码实验测试

代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main ()
{
    pid_t fpid;
    int count=0;
    asm volatile(
        "mov $0,%%ebxnt"
        "mov $0xd,%%eaxnt"
        "int $0x80nt"
        "mov %%eax,%0nt"
        :"=m"(fpid)
    );
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0)
    {
        printf("I am the child process, my process id is %dn",getpid());
        count++;
    }
    else
    {
        printf("I am the parent process, my process id is %dn",getpid());
        count++;
    }
    printf("Result is: %dn",count);
    return 0;
}

 效果图

分析

此处依旧以分析汇编为例(主要api没可分析的)。

首先将ebx清零,使用eax传递系统调用号,此处设为2,之后fork()函数(其系统调用对应的api)运行,期间触发int 0x80的中断完成由用户态进入内核态的转变过程,在执行完系统调用后,其系统调用的返回值使用eax存储。

int 0x80的中断向量对应着system_call()内核代码的入口,中间执行到对应的system_fork()中断服务程序,之后ret_from_sys_call,过程中可能发生进程调度,若没发生则返回到用户态继续进行其他的。

当初由于没仔细看视频于是有了上面最后的代码实验测试,在eax处设了个13,调成time的系统调用号了,故最后一张图中打印出来的仅有一个主程序。

总结

系统通过中断的方式完成用户态到内核态的转换过程,同时调用系统函数实现系统功能。当进入系统中断时,先保护现场,即保存需要用到的寄存器的数据,中断完成后恢复现场,即退出中断程序,恢复保存寄存器的数据。

windCoder原创作品转载请注明出处

参考资料

Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

实验代码参考地址:http://blog.csdn.net/myfather103/article/details/44496605

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习实践二三事

Ipynb文件的打开

RT,ipynb文件用gedit直接打开的话,太多附加信息,此时需要在浏览器端打开 升级ipython 太低版本的ipython是不行的,出现的错误可能是这样的...

2258
来自专栏杨建荣的学习笔记

关于shell中的pl/sql脚本错误排查与分析(r4笔记第21天)

今天有个同事问我一个问题,他说运行shell脚本的时候抛出了ORA 错误,但是对于错误的原因没有思路,想让我帮他看看。 我查看了下,脚本的结构比较清晰。 脚本是...

3145
来自专栏抠抠空间

Node.js基础

2800
来自专栏静下来

解决ssh出现Host key verification failed错误的方法

image.png ssh登陆Linux服务器的时候,如果出现了Host key verification failed的错误,需要清空下本地ip密码记录。 出...

3577
来自专栏木子昭的博客

在Chrome中使用ssh使用一种什么体验

4364
来自专栏Web项目聚集地

Maven学习笔记(一)

本教程作者是「小灯光环」,作者简介:全栈开发工程师,CSDN博客专家,CSDN论坛 Java Web/Java EE版主,热爱技术,乐于分享,在分布式Web开发...

812
来自专栏JMCui

Linux 学习记录 二 (文件的打包压缩).

 前言:本文参考《鸟哥的Linux 私房菜》,如有说的不对的地方,还请指正!谢谢!  环境:Centos 6.4  和window不同,在Linux压缩文件需要...

3595
来自专栏zhisheng

Python爬虫入门三之Urllib库的基本使用

那么接下来,小伙伴们就一起和我真正迈向我们的爬虫之路吧。 1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的...

3665
来自专栏专业duilib使用+业余界面开发

duilib中list拖动表头大小内容大小跟随变化的一个示例

2104
来自专栏飞雪无情的博客

Go语言实战笔记(十二)| Go goroutine

一般的程序,如果没有特别的要求的话,是顺序执行的,这样的程序也容易编写维护。但是随着科技的发展、业务的演进,我们不得不变写可以并行的程序,因为这样有很多好处。

1183

扫码关注云+社区

领取腾讯云代金券