1. 内核部分
1-1. 系统调用函数的定义
系统调用函数的原型定义在内核代码include/linux/syscalls.h中,
除此之外在该头文件中还提供了如下的宏
#define __SC_DECL1(t1, a1) t1 a1 #define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__) ... #define __SC_DECL6(t6, a6, ...) t6 a6, __SC_DECL5(__VA_ARGS__) #define SYSCALL_DEFINE(name) asmlinkage long sys_##name #define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__)) #define SYSCALL_DEFINEx(x, sname, ...) \ __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) ... #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
系统调用函数的定义分散在内核的各个模块,内核的各个模块使用上面宏构建系统调用函数。
以socket相关的系统调用函数为例,
socket相关的系统调用函数定义在net/socket.c中,有一个共通的接口,其定义如下:
SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
该函数编译展开后,可以得到如下的函数
asmlinkage long sys_socketcall(int call, unsigned long __user *args)
1-2. 系统调用表
每一个系统调用都有自己的编号,以x86架构的系统为例,
系统调用的编号保存在如下的文件中
arch/x86/include/asm/unistd_64.h
arch/x86/include/asm/unistd_32.h
而系统调用表sys_call_table则定义在如下的文件中
arch/x86/kernel/syscall_table_32.S
arch/x86/kernel/syscall_64.c
根据系统调用编号,可以在系统调用表中找到相应的系统调用函数。
1-3. 系统调用初始化
在x86架构中,系统调用是通过软件中断0x80来触发的。
linux系统在启动时使用如下的方式注册0x80软件中断的处理函数
start_kernel(void)[init/main.c]
`-- trap_init(void)[arch/x86/kernel/traps.c]
`-- set_system_trap_gate(SYSCALL_VECTOR, &system_call)[arch/x86/include/asm/desc.h]
system_call函数是由汇编实现的,其实现在如下文件中可以找到
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
system_call根据传入的系统调用编号结合系统调用表,找到并执行相应的系统调用处理函数。
2. glibc
glibc对系统调用进行了封装,简化了系统调用的使用。以socket相关的系统调用函数为例进行说明。
socket相关的系统调用实际上都是执行内核中的sys_socketcall函数,sys_socketcall会根据传入的参数call决定具体执行哪个处理函数。在内核中call定义在include/linux/net.h中,而在glibc中则提供了一个相同的头文件sysdeps/unix/sysv/linux/socketcall.h
glibc中socket相关的系统调用,共通处理部分定义在如下的文件中
sysdeps/unix/sysv/linux/sh/socket.S
sysdeps/unix/sysv/linux/i386/socket.S
其它socket相关的系统调用函数则定义在sysdeps/unix/sysv/linux目录下
当socket.S未被其它文件引入时socket.S会生成socket函数,而当被其它文件引入时则会生成引入文件对应的函数。
以bind为例,bind.S通过引入socket.S来生成bind函数
sysdeps/unix/sysv/linux/bind.S
#define socket bind #define NARGS 3 #define NO_WEAK_ALIAS 1 #include <socket.S> weak_alias (bind, __bind)
在socket.S中系统调用的编号和call会被传递给内核,内核根据系统调用编号和call决定接下来执行哪个具体的处理函数。当系统调用函数实际上不存在时,则实际会调用socket/socket.c中的socket函数
int __socket (domain, type, protocol) int domain; int type; int protocol; { __set_errno (ENOSYS); return -1; }
此时就会返回错误,并且将errno设置为ENOSYS。
相关推荐
Linux内核bridge浅析是Linux操作系统中的一种网桥模型,用于连接和桥接多个以太网接口设备。下面是对Linux内核bridge浅析的详细说明: 网桥模型 Linux内核通过一个虚拟的网桥设备来实现桥接的,这个设备可以绑定...
Linux内核配置系统是Linux操作系统开发中的核心组成部分,它允许开发者根据特定的需求定制内核,以便在不同的硬件平台上实现最佳性能和功能。随着Linux在嵌入式领域的广泛使用,掌握内核配置系统的知识变得越来越...
# Linux 设备模型浅析 —— 设备篇 ## 前言 为了更好地理解Linux设备模型,我们可以通过结合理论介绍和内核代码的方式来进行学习。这样不仅能让我们更直观地了解概念,还能深入掌握其实现细节。本文将以S3C2410RTC...
总之,Linux内核的Makefile系统是一个复杂而精细的工程,它使得庞大的内核源码能够根据用户的定制需求,有效地进行编译和构建。理解这个系统对于内核开发和调试至关重要,尤其是在进行内核模块开发或定制内核功能时...
### Linux下字符设备驱动开发浅析 #### 一、字符设备驱动的概念与作用 字符设备驱动在Linux系统中扮演着连接内核与用户空间应用程序的关键角色。它是一种相对简单但功能强大的驱动类型,主要用于处理串行数据传输...
【嵌入式Linux内核Makefile浅析】 嵌入式Linux内核的构建过程中,Makefile扮演着至关重要的角色,它是整个编译过程的核心。Makefile不仅定义了编译规则,还负责根据用户配置生成相应的源文件列表并进行编译。在深入...
### Linux设备模型浅析之uevent篇 #### 一、引言 在深入探讨`uevent`机制前,我们先回顾一下Linux设备模型的基本概念。Linux设备模型是Linux内核中用于管理硬件设备的一种框架,它提供了一种统一的方式来处理各种...
《Linux环境下基于TCP的Socket编程浅析》 在现代计算机科学中,Socket编程是构建网络应用程序的基础,尤其在Linux操作系统中,它的重要性更是不言而喻。Socket提供了一种标准接口,使得进程间通信(IPC)以及网络...
示例源代码tst.c是一个简单的C语言程序,包含一个计算求和的函数func和主函数main,分别计算从1到100的累加和以及调用func函数计算到250的累加和。 编译生成执行文件: ```bash hchen/test> cc -g tst.c -o tst ```...
本文将深入探讨firmware的完整生存和使用流程,重点关注在Linux环境下的开发和应用。 首先,firmware的生存流程包括以下几个关键步骤: 1. **设计与编写**: firmware的开发始于需求分析,根据硬件设备的功能需求...
Linux开发工具ADB(Android Debug Bridge)是Android系统中不可或缺的一部分,它为开发者提供了一种与Android设备进行通信的桥梁。本文将深入剖析ADB的具体实现,包括ADB如何启动、ADB服务器与设备之间的通信流程...
在Linux内核中,驱动程序是操作系统与硬件设备之间的桥梁,负责初始化、管理和操作特定的硬件设备。在本文中,我们将深入分析Linux 2.6.30.4内核中的uda134x声卡驱动源码,了解声卡驱动的注册与工作流程。 uda134x...
3. **加载固件**:一旦找到固件文件,驱动程序会调用`request_firmware()`函数向固件加载子系统发送请求,加载固件到内存中。 4. **传递固件**:固件加载子系统会读取文件内容并将其传递给驱动程序,然后驱动程序...
9 2.1.2 ARM处理器体系结构........................................................................................ 10 2.1.3 Linux 与ARM处理器.....3.6.2 Linux 系统调用.........................................
7. **多进程编程**:理解Linux系统中的进程概念,如何创建和管理进程,编写守护进程,并使用系统调用进行同步和通信,如管道、信号和共享内存。 8. **多线程编程**:线程是提高系统效率的关键。学习多线程编程方法...
在安全上下文中,我们可以利用这一模式来构造安全的API调用,防止命令注入攻击。 SSH(Secure Shell)在工控安全领域扮演着重要角色。虽然SSH主要用于远程登录和命令执行,但在安卓APP中,它可能用于安全地连接到...
U-BOOT的启动过程对于理解整个系统的启动流程非常重要。以下是U-BOOT启动的主要步骤: 1. **内存初始化**:系统启动时,CPU首先映射FLASH到其内存空间。此时,U-BOOT位于FLASH上,CPU会执行其中的代码。初始化内存...