原 Linux下嵌入汇编代码调用API(u

以下关于fork()的描述来自于:jason314

首先,在Linux环境下,一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

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

在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

现在,我们来写一段程序,使用API调用fork:

#include <stdio.h>
#include <unistd.h>

int main()
{
    pid_t fpid;
    int count = 0;
    fpid = fork();
    printf("Now pid = %d\n", 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("Now count = %d\n", count);
    return 0;
}

在第八行执行完fork后,父进程中有count=0、fpid=子进程的pid;子进程中变量为count=0、 fpid=0,这两个进程的变量都是独立的,存在不同的地址中,也不是共用的。可以说,我们就是通过fpid来识别和操作父子进程的。

在x86的系统中,%eax寄存器在进行系统调用前储存系统调用号。另外,由于六个及以上参数的系统调用并不多见,因此一般使用%ebx、%ecx、%edx、%esi和%edi依次存放前五个参数。如果出现六个以上参数的情况,应该用一个单独的寄存器存放指向所有这些参数在用户空间地址的指针。当调用结束后,函数的返回值存放在%eax中。

下面,我们将改写fork.c,直接嵌入汇编语言进行系统调用:

#include <stdio.h>
#include <unistd.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)
            );
    printf("Now pid = %d\n", 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("Now count = %d\n", count);
    return 0;
}

总结:API与系统调用并不是一一对应的关系(Linux系统可以参考syscalls),它为程序提供了标准接口。而内核基本只与系统调用打交道;当然,我们也可以直接使用系统调用写程序,但势必会降低程序的可移植性。至于APIs如何进行系统调用,那就是Glibc等标准制定者的事了。

陈政/arc001    原创作品转载请注明出处  《Linux内核分析》MOOC课程

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

[WCF安全系列]绑定、安全模式与客户端凭证类型:BasicHttpBinding

整个安全传输是在WCF的信道层进行的,而绑定是信道层的缔造者,所以终结点采用哪种类型的绑定以及对绑定的属性进行怎样的设置决定了信道层最终采用何种机制实现消息的安...

2419
来自专栏ImportSource

单线程的Redis为什么辣么快?

你之所以问这样的问题。是因为你认为只有多线程分别接收connection才可以更快,就像过去的tomcat那样,同时开多个线程来响应。

1022
来自专栏coding

python的多进程与多fork

1633
来自专栏决胜机器学习

《Redis设计与实现》读书笔记(二十九) ——Redis集群执行命令与重新分片

《Redis设计与实现》读书笔记(二十九) ——Redis集群执行命令与重新分片 (原创内容,转载请注明来源,谢谢) 一、集群中执行命令 1、节点对命令的判断 ...

3266
来自专栏运维小白

Linux基础(day18)

5.5 进入编辑模式 编辑模式:就是进入到可以编辑文本文件的模式 ? 进入编辑模式方法: i ,直接在当前光标处进入编辑模式 I (大写I),光标直接移动到...

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

Go语言实战笔记(十四)| Go 通道

上一篇我们讲的原子函数和互斥锁,都可以保证共享数据的读写,但是呢,它们还是有点复杂,而且影响性能,对此,Go又为我们提供了一种工具,这就是通道。

1043
来自专栏阮一峰的网络日志

浏览器加载 CommonJS 模块的原理与实现

就在这个周末,npm 超过了 cpan ,成为地球上最大的软件模块仓库。 npm 的模块都是 JavaScript 语言写的,但浏览器用不了,因为不支持 Com...

3668
来自专栏肖洒的博客

【MOOC】Python网络爬虫与信息提取

Python网络爬虫与信息提取-北京理工大学-嵩天 发布大学:北京理工大学 发布课程:Python网络爬虫与信息提取 授课老师:嵩天 课程简介:“The web...

1202
来自专栏三木的博客

Linux shell 程序设计3——命令行程序

1、date:显示、设置系统的日期和时间。 $date 2011年 01月 30日 星期日 14:43:35 CST $date 012309232011 执行...

2086
来自专栏landv

CMD批处理——forfiles命令使用,自动删除过期备份文件

2391

扫码关注云+社区

领取腾讯云代金券