【Linux102】21-include/asm/segment.h


公粽号「专注Linux」,专注Linux内核开发

Linux102系列会详细讲解Linux0.11版本中的102个文件,本文讲解linux0.11的第20个文件include/asm/segment.h的文件源码。

1.include/asm/segment.h的作用

本程序定义了一系列用于在 Linux 内核中访问用户空间内存内联函数,主要通过内嵌汇编操作段寄存器fs来实现内核用户空间的数据交互。


这些函数是早期 Linux 内核中用于内核态与用户态数据交互的核心工具:

get_fs_xxx系列从用户空间(fs段指向的内存)读取数据到内核。
put_fs_xxx系列从内核写入数据到用户空间(fs段指向的内存)。
get_fs()/set_fs()系列获取 / 设置fs段寄存器,用于切换内存访问的上下文(如从内核段切换到用户段)。

通过操作fs段寄存器内核可以安全地访问用户空间的内存,这是系统调用进程管理等功能的基础。


2.源码注释版本

本源码使用了C与汇编嵌入使用的情况,这种情况详见本文:😉【C语言】C语言嵌入汇编程序


/**
* func descp: 代码文件总体分析
*/
// 定义了一系列用于在 Linux 内核中访问用户空间内存的内联函数,
// 主要通过内嵌汇编操作段寄存器fs来实现内核与用户空间的数据交互。以下是逐行解析:

// 功能:从用户空间地址addr读取 1 个字节(8 位)。
// 汇编解析:movb %%fs:%1,%0表示从fs段选择符指定的内存段中,
// 读取%1(即*addr指向的内存)的 1 字节数据到%0(即变量_v)。
// "=r" (_v)表示_v是输出寄存器,"m" (*addr)表示*addr是内存输入。

static inline unsigned char get_fs_byte(const char * addr)
{
	unsigned register char _v;

	__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
	return _v;
}

// 功能:从用户空间地址addr读取 1 个字(16 位)。
// 汇编解析:movw是 16 位数据传输指令,从fs段的*addr读取 2 字节到_v。
static inline unsigned short get_fs_word(const unsigned short *addr)
{
	unsigned short _v;

	__asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
	return _v;
}

// 功能:从用户空间地址addr读取 1 个长字(32 位)。
// 汇编解析:movl是 32 位数据传输指令,从fs段的*addr读取 4 字节到_v。
static inline unsigned long get_fs_long(const unsigned long *addr)
{
	unsigned long _v;

	__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
	return _v;
}

// 功能:向用户空间地址addr写入 1 个字节(8 位)。
// 汇编解析:movb %0,%%fs:%1表示将%0(即val)的 1 字节数据写入fs段的%1
// (即*addr指向的内存)。"r" (val)表示val是寄存器输入,"m" (*addr)表示*addr是内存输出。

static inline void put_fs_byte(char val,char *addr)
{
__asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
}

// 功能:向用户空间地址addr写入 1 个字(16 位)。
// 汇编解析:movw是 16 位传输指令,将val写入fs段的*addr。
static inline void put_fs_word(short val,short * addr)
{
__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
}

// 功能:向用户空间地址addr写入 1 个长字(32 位)。
// 汇编解析:movl是 32 位传输指令,将val写入fs段的*addr。
static inline void put_fs_long(unsigned long val,unsigned long * addr)
{
__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
}

/*
 *要是有谁比我更懂 GNU 汇编,还请帮忙再检查下下面这段代码。
 *它目前看起来能正常工作,但我不确定自己有没有犯什么不易察觉的错误。
 *——TYT,1991 年 11 月 24 日
 *[这段代码没问题,林纳斯] // 林纳斯(Linux 创始人)确认代码无误
 */

 // 功能:获取当前fs段寄存器的值(16 位段选择符)。
// 汇编解析:mov %%fs,%%ax将fs寄存器的值传输到ax通用寄存器,
// "=a" (_v)表示将ax的值存入_v。
static inline unsigned long get_fs() 
{
	unsigned short _v;
	__asm__("mov %%fs,%%ax":"=a" (_v):);
	return _v;
}

// 功能:获取当前ds段寄存器的值(ds通常指向内核数据段)。
// 汇编解析:类似get_fs(),但操作的是ds段寄存器。
static inline unsigned long get_ds() 
{
	unsigned short _v;
	__asm__("mov %%ds,%%ax":"=a" (_v):);
	return _v;
}

// 功能:设置fs段寄存器的值(通常用于切换到用户空间的段选择符)。
// 汇编解析:mov %0,%%fs将%0(即val,转换为 16 位)写入fs寄存器,
// "a" (...)表示使用ax寄存器传递值。
static inline void set_fs(unsigned long val)
{
	__asm__("mov %0,%%fs"::"a" ((unsigned short) val));
}

3.源码完整版

static inline unsigned char get_fs_byte(const char *addr)
{
    unsigned register char _v;

    __asm__("movb %%fs:%1,%0" : "=r"(_v) : "m"(*addr));
    return _v;
}

static inline unsigned short get_fs_word(const unsigned short *addr)
{
    unsigned short _v;

    __asm__("movw %%fs:%1,%0" : "=r"(_v) : "m"(*addr));
    return _v;
}

static inline unsigned long get_fs_long(const unsigned long *addr)
{
    unsigned long _v;

    __asm__("movl %%fs:%1,%0" : "=r"(_v) : "m"(*addr));
    return _v;
}

static inline void put_fs_byte(char val, char *addr)
{
    __asm__("movb %0,%%fs:%1" ::"r"(val), "m"(*addr));
}

static inline void put_fs_word(short val, short *addr)
{
    __asm__("movw %0,%%fs:%1" ::"r"(val), "m"(*addr));
}

static inline void put_fs_long(unsigned long val, unsigned long *addr)
{
    __asm__("movl %0,%%fs:%1" ::"r"(val), "m"(*addr));
}

static inline unsigned long get_fs()
{
    unsigned short _v;
    __asm__("mov %%fs,%%ax" : "=a"(_v) :);
    return _v;
}

static inline unsigned long get_ds()
{
    unsigned short _v;
    __asm__("mov %%ds,%%ax" : "=a"(_v) :);
    return _v;
}

static inline void set_fs(unsigned long val)
{
    __asm__("mov %0,%%fs" ::"a"((unsigned short)val));
}

4.源码图像版

include/asm/segment.h源码图像版

5.源码注释版图像

include/asm/segment.h源码注释版图像版


总的来说,本程序定义系列函数,就是通过fs段寄存器来完成内核与用户态的数据交互的。就这么简单!



汇编语言

😉【汇编语言】1—基础硬件知识

😉【汇编语言】2—寄存器基础知识

😉【汇编语言】3-寄存器与内存的交互

😉【汇编语言】4-第一个完整的汇编程序

😉【汇编语言】5-[BX]和loop指令

😉【汇编语言】6-包含多个段的程序

😉【汇编语言】7-灵活的5大寻址方式

😉【汇编语言】8-1-数据的位置

😉【汇编语言】8-2-数据的长度

😉【汇编语言】8-数据处理的两个基本问题(位置与长度)

😉【DOSBox】1-debug

😉【DOSBox】2-debug可执行文件

😉【DOSBox】3-完整开发流程


C语言

本系列将直击C语言的本质基础,流利处理出各个易错、实用的实战点,并非从零开始学习C。

😉【C语言】C Token(C89 C99 C11)

😉【C语言】指针基础

😉【C语言】数组基础

😉【C语言】结构体对齐

😉【C语言】华为C语言进阶测试

😉【C语言】触发刷新到磁盘的方式总结

😉【C语言】C语言文件操作的mode详解

😉【C语言】C语言文件知识全讲解

😉【C语言】从extern到头文件包含的最优实践

😉【C语言】C语言的关键字与重载机制

😉【C语言】长字符串的2种处理方式

😉【C语言】C语言嵌入汇编程序

😉【C语言】指针数组 VS 数组指针 原来这么简单!

😉【C语言】深浅拷贝、传参、赋值 本质剖析

😉【C语言】find-in-linux递归搜索文件名函数

😉【C陷阱与缺陷】-1-词法陷阱

😉【C陷阱与缺陷】-2-语法陷阱

😉【C陷阱与缺陷】-3-语义陷阱


Linux101系列

专注讲解Linux中的常用命令,共计发布100+文章。

😉【Linux101-1】ls

😉【Linux101-1】ls -l命令输出结果全解析

😉【Linux101-2】cd

😉【Linux101-3】cat

😉【Linux101-4】tac

😉【Linux101-5】head

😉【Linux101-6】tail

😉【Linux101-7】pwd

😉【Linux101-8】touch

😉【Linux101-9】cal

😉【Linux101-10】bc

😉【Linux101-11】df

😉【Linux101-12】uname

😉【Linux101-13】mkdir

😉【Linux101-14】gzip

😉【Linux101-15】tar

😉【Linux101-16】lsof

😉【Linux101-17】du

😉【Linux101-18】stat


Linux102系列

本系列将精讲Linux0.11内核中的每一个文件,共计会发布100+文章。

😉【Linux102】1-Makefile

😉【Linux102】2-Makefile.header

😉【Linux102】3-system.map

😉【Linux102】4-bootsect.s

😉【Linux102】5-setup.s

😉【Linux102】6-head.s

😉【Linux102-D】/boot

😉【Linux102】7-main.c

😉【Linux102】8-kernel/asm.s

😉【Linux102】9-kernel/traps.c

😉【Linux102】10-kernel/printk.c

😉【Linux102】11-kernel/vsprintf.c

😉【Linux102】12-include/stdarg.h

😉【Linux102】13-kernel/mktime.c

😉【Linux102】14-kernel/system_call.s

😉【Linux102】18-include/signal.h

😉【Linux102】19-include/sys/types.h

😉【Linux102】20-include/linux/kernel.h

😉【Linux102】21-include/asm/segment.h


Linux内核精讲系列

和Linux内核102系列不同,本系列将会从全局描绘Linux内核的各个模块,而非逐行源码分析,适合想对Linux系统有宏观了解的家人阅读。

😉【Linux】学习Linux前必备的知识点

😉【Linux】Linux内核对进程的内存抽象

😉【Linux】Linux概述1-linux对物理内存的使用

😉【Linux】软件从写下到运行的全部流程

😉【Linux】CPU的三寻址:实模式、保护模式、长模式

😉【Linux】实模式与保护模式的寻址, 这次讲明白了!

😉【Linux】linux0.11的源码目录架构

😉【Linux】Makefile机制及基础详解

😉【Linux】编译并运行Linux0.11

😉【Linux】“进进内网文”—Linux的内核结构全貌

😉【Linux】linux的中断机制

😉【Linux】linux进程描述


关于小希

😉嘿嘿嘿,我是小希,专注Linux内核领域,同时讲解C语言汇编等知识。

我的微信:C_Linux_Cloud,期待与您学习交流!

加微信请备注哦


小希的座右铭:别看简单,简单也是难。别看难,难也是简单。我的文章都是讲述简单的知识,如果你喜欢这种风格:

不妨关注、评论、转发,让更多朋友看到哦~~~🙈

下一期想看什么?在评论区留言吧!我们下期见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值