Linux系统调用内核分析

高端的程序员往往采用最朴素的编程方式。

1635341692109

能不能复用别人的代码,避免重复造轮子,是衡量程序员工作效率、是否能按时下班的关键。我们编写一个add()函数,只要封装得好,就可以给很多人使用,这样就可以减少他人重复劳动,避免重复造轮子。

// add.c 
int add(int a, int b)
{
   return a + b;
}

//add.h
int add(int a, int b);`

其他的开发者,需要调用add()时,只要在自己的程序中使用#include包含对应的头文件add.h,就可以直接调用add()函数,不用自己再写一遍了。

我们将很多类似的函数打包,归档成一个库,引出对应的头文件声明,就可以供很多人调用和使用了。

# gcc -c add.c -o add.o
# gcc -c sub.c -o sub.o
# ar rcs libmath.a add.o sub.o

将这些库,放到操作系统的指定官方目录(如/lib、/usr/lib),随操作系统一起发布,对应函数的声明头文件(add.h sub.h),也放在操作系统的指定目录(如/usr/include)。程序开发者就可以在他们的程序中直接使用这些函数了:

#include <add.h>
int main(void)
{
    int sum = 0;
    sum = add(3, 4);

    return 0;
}

然后我们在编译程序时指定需要的链接库就可以了:

# gcc main.c  -L. -lmath

如果一些库在编译参数设置时是默认链接的,如C标准库,就不需要显式指定要链接的库了,直接编译程序就可以了。

如果从软件复用的角度看操作系统,操作系统其实也可看做一个库:操作系统对计算机的资源做了各种封装:任务创建、内存管理、文件系统、网络通信,并引出一系列接口给用户使用,避免用户重复造轮子。以uc/os为例,我们需要创建一个多任务程序,就可以直接将uc/os源码直接导入到我们的项目中,然后直接调用uc/os提供的接口即可:

#include "ucos_ii.h"

int main(void)
{
   OSInit();    //初始化OS
   OSTaskCreate();//创建一个任务
   OSStart();   //开启任务调度
}

到了Linux时代,操作系统发布商、应用程序开发者开始分离,由不同的团队和公司完成开发。用户可以自己下载自己喜欢的软件安装到电脑上,成千上万的开发者,成千上万的软件,对安全构成了很大的挑战。为了安全起见,Linux使用了权限管理:操作系统和应用程序分别运行在内核态和用户态,具有不同的权限:应用程序运行在普通权限下,不能访问硬件,而操作系统则运行在特权模式下,可以直接操作系统,读写寄存器,切换CPU的工作模式…

有了权限管理,Linux内核实现的各种函数接口,应用程序就无法像uc/os那样直接调用了。但Linux内核向应用程序提供了系统调用的访问接口:软中断指令,如X86的处理器的INT指令,ARM处理器的SWI/SVC指令,应用程序可以通过软中断,陷入Linux内核,去执行内核实现的各种的接口函数。

#include <sys/types.h>
#include <unistd.h>

int main()
{
   pid_t pid;

   pid = fork();
   if(pid < 0)
       printf("fork failed!\n");
   else if(pid == 0)
       printf("child process\n"); 
   else
       printf("parent process\n");
   return 0;
}

其中的fork只是一个系统调用接口函数,真正的实现是在内核中的sys_fork()中实现的。C标准库glibc再对这些接口进行封装,就成了我们大家熟悉的read、write、open、close等系统调用函数了,用户就可以像调用普通函数一样,通过这些接口,去调用Linux内核中实现的各种系统调用函数了。

想要了解系统调用更多细节:比如在X86、ARM架构上的不同实现,CPU、操作系统和glibc三者是如何配合的,包括最新版本内核使用的快速系统调用、虚拟系统调用、VDSO是怎么回事,请关注 《Linux内核编程》第03期:系统调用。

Linux内核编程第03期:系统调用,已发布,课程已更新到网盘。

本期课程主要内容:

  • 系统调用的基本概念
  • 软中断:系统调用的入口(ARM)
  • 软中断:系统调用的入口(X86)
  • 系统调用的接口封装:glibc
  • 系统调用的接口封装:syscall
  • 系统调用流程分析
  • 添加一个系统调用
  • 系统调用的开销
  • 快速系统调用
  • 虚拟系统调用:vsyscall
  • 虚拟动态共享对象:VDSO
  • 从系统调用角度看文件的读写流程

本期课程共12个课时,视频总大小1.56GB,总时长3小时9分钟。
1635341915899
更详细的课程介绍请参考淘宝店:Linux内核编程实战:驱动开发入门教程,Linux内核核心理论

一线原厂驱动开发经验,专门为嵌入式精心打造的嵌入式进阶视频教程,详情请点击:王利涛老师个人店