linux0.12-8-4-sys_call.s

news/2024/5/19 0:28:00/文章来源:https://blog.csdn.net/qq_31806069/article/details/130503070

[301页]

8-4 sys_call.s 程序

sys_call.s 程序简单总结:
int 0x80 – _system_call
int16 – 处理器错误中断
int7 – 设备不存在或协处理器不存在。
int32 – (int 0x20)时钟中断处理程序。
两个系统功能的底层接口,分别是 sys_execve 和 sys_fork 。
int46 – (int 0x2E)硬盘中断处理程序
int32 – (int 0x26)软盘驱动器中断处理程序
int39 – (int 0x27)并行口中断处理程序

8-4-1 功能描述

(a)在linux0.12中,用户使用中断调用int 0x80和放在寄存器eax中的功能号来使用内核提供的各种功能服务,这些操作系统体用的功能被称为系统调用功能。
(b)通常用户并不是直接使用系统调用中断,而是通过函数库(例如libc)中提供的接口函数来调用的。例如创建进程的系统调用fork可直接使用函数fork()即可。函数库libc中的fork()函数会实现对中断int0x80的调用
过程并把调用结果返回给用户程序。
©对于所有系统调用的实现函数,内核把它们按照系统调用功能号顺序排列成一张函数指针(地址)表(在include/linux/sys.h文件中)。然后在中断int0x80的处理过程中 根据用户提供的功能号 调用对应 系统调用函数建处理。
(d)本程序主要实现系统调用(system_call)中断int0x80的入口处理过程以及信号检查处理(从代码第80行开始),同时给出了两个系统功能的底层接口,分别是sys_execve和sys_fork。还是有列出了处理过程类似的
协处理器出差(int16)、
设备不存在(int7)、
时钟中断(int32)、
硬盘中断(int46)、
软盘中断(int38)的中断处理程序。
(e)对于软中断(system_call、coprocessor_error、device_not_available),其处理过程基本上是首先为调用相应C函数处理程序作准备,将一些参数压入堆栈。系统调用最多可以带3个参数,分别通过寄存器ebx、ecx和edx传入。然后调用C函数进行相应功能的处理,处理返回后再去检查当前任务的信号位图,对值最小的一个信号进行处理并复位信号位图中的该信号。系统调用的C语言处理函数分布在整个linux内核代码中,由include/linux/sys.h头文件中的系统函数指针数组表来匹配。
(f)对于硬件中断请求信号IRQ发来的中断,其处理过程首先是向中断控制芯片8259A发送结束硬件中断控制指令EOI,然后 调用相应的C函数处理程序。对于时钟中断也要对当前任务的信号位图进行检测处理。系统调用(int 0x80)
(a)对于系统调用(int 0x80)的中断处理过程,可以把它看作是一个"接口程序"。
实际上每个系统调用功能的处理过程基本上都是通过调用相应的C函数进行的。即所谓的"Bottom half"函数。
(b)这个程序在刚执行时会首先检查eax中的功能号是否有效(在给定的范围内),然后保存一些会用到的寄存器到堆栈上。Linux内核默认把段寄存器ds,es用于内核数据段,而fs用于用户数据段。接着通过一个地址跳转表(sys_call_table)
调用相应系统调用的C函数。在C函数返回后,程序就把返回值压入堆栈保存起来。
©接下来,该程序查看执行本次调用进程的状态。如果由于上面C函数的操作或者其他情况而是进程的状态从执行态变成了其他状态,或者由于时间片已经用完(counter==0),则调用进程调度函数schedule()(jmp _schedule)。由于在执行jmp _schedule之前已经把返回地址ret_from_sys_call入栈,因此在执行完schedule()后最终会返回到ret_from_sys_call处继续执行。
(d)从 ret_from_sys_call标号处开始的代码执行一些系统调用的后处理工作。主要判断当前进程是否初始进程0,如果是就直接退出此次系统调用,中断返回。否则根据代码段描述符和所使用的堆栈来判断本次调用的进程是不是一个普通进程,
若不是则说明是内核进程(例如初始进程1)或其他。则也会立刻弹出堆栈内容退出系统调用中断。末端的一块代码用来处理调用系统调用进程的信号。若进程结构的信号位图表明该进程接收到信号,则调用信号处理函数do_signal()。
(e)最后,该程序回复保存的寄存器内容,退出此次中断处理过程并返回调用程序。若有信号时则程序会首先"返回"到相应信号处理函数中去执行,然后返回调用system_call的程序。

8-4-2 代码注释


/**  linux/kernel/system_call.s**  (C) 1991  Linus Torvalds*//*
system_call.s文件包含系统调用(system-call)底层处理子程序。由于有些代码比较类似,
所以同时也包括时钟中断处理timer-interrupt句柄。硬盘和软盘的中断处理程序也在这里。注意:这段代码处理信号(signal)识别,在每次时钟中断和系统调用之后都会进行识别。
一般中断过程并不处理信号识别,因为会给系统造成混乱。
从系统调用返回('ret_from_system_call')时堆栈的内容见上面19-30行。#上面linus原注释中一般中断过程是指除了系统调用中断(int 0x80)和时钟中断(int 0x20)
#以外的其他中断。这些中断会在内核态或用户态随机发生,若在这些中断过程中也处理信号识别的话,
#就有可能与系统调用中断和时钟中断过程中对信号的识别处理过程相冲突,违反了内核代码非抢占
#原则。因此系统无必要在这些“其他”中断中处理信号,也不允许这样做。*/SIG_CHLD	= 17		#定义SIG_CHLD信号(子进程停止或结束)。EAX		= 0x00			#堆栈中各个寄存器的偏移位置。
EBX		= 0x04
ECX		= 0x08
EDX		= 0x0C
ORIG_EAX	= 0x10		#如果不是系统调用(是其他中断)时,该值为-1。
FS		= 0x14
ES		= 0x18
DS		= 0x1C
EIP		= 0x20			#这一行 -- (OLDSS=0x30)行 由CPU自动入栈。
CS		= 0x24
EFLAGS		= 0x28
OLDESP		= 0x2C		#当特权级变化时,原堆栈指针也会入栈。
OLDSS		= 0x30#以下这些是任务结构(task_struct)中变量的偏移值,参见include/linux/sched.h,105行开始。
state	= 0			# these are offsets into the task-struct. #进程状态码。
counter	= 4			# 任务运行时间技术(递减)(滴答数),运行时间片。
priority = 8		# 运行优先数。任务开始运行时counter=priority,越大则运行时间越长。
signal	= 12		# 是信号位图,每个位代表一种信号,信号值=位偏移值+1.
sigaction = 16		# MUST be 16 (=len of sigaction) #sigaction结构长度必须是16字节。
blocked = (33*16)	# 受阻塞信号位图的偏移量。# 以下定义在sigaction结构体中的偏移量,参见include/signal.h,55行开始
sa_handler = 0		# 信号处理过程的句柄(描述符)。
sa_mask = 4			#信号屏蔽码。
sa_flags = 8		#信号集。
sa_restorer = 12	#恢复函数指针,参见kernel/signal.c程序说明。nr_system_calls = 82	#Linux 0.12版内核中的系统调用总数。ENOSYS = 38			#系统调用号出错码。/*
好了,在使用软驱时我收到了并行打印机中断,很奇怪。呵,现在不管它。*/
.globl _system_call,_sys_fork,_timer_interrupt,_sys_execve
.globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
.globl _device_not_available, _coprocessor_error#系统调用号错误时将返回出错码-ENOSYS
.align 2						#内存4字节对齐。
bad_sys_call:pushl $-ENOSYS				#eax中置-ENOSYS。jmp ret_from_sys_call# 重新执行调度程序入口。调度程序schedule()在kernel/sched.c,119行处开始。
# 当调度程序schedule()返回是就从ret_from_sys_call处(107)继续执行。
.align 2
reschedule:pushl $ret_from_sys_call	#将ret_from_sys_call的地址入栈(107)。jmp _schedule#int 0x80 -- linux系统调用入口点(调用中断 int 0x80,eax中时调用号)
.align 2
_system_call:push %ds		# 保存原段寄存器值。push %espush %fspushl %eax		# save the orig_eax #保存eax原值。# 一个系统调用最多可带有3个参数,也可以不带参数。下面入栈的ebx、ecx和edx中放着系统# 调用相应C语言函数(见第99行)的调用参数。这几个寄存器入栈的属性是由GUN gcc规定的,# ebx中可存放第1个参数,ecx中存放第二个参数,edx中存放第3个参数。#系统调用语句可参见头文件includeunistd.h中第150200行的系统调用宏。pushl %edx		pushl %ecx		# push %ebx,%ecx,%edx as parameterspushl %ebx		# to the system call# 在保存过段寄存器之后,让ds,es指向内核数据段,而fs指向当前局部数据段,即指向指行本次系统# 调用的用户程序的数据段。注意,在Linux 0.12中内核给任务分配的代码和数据内存段是重叠的,# 它们的段基址和段限长是相同。参见fork.c程序中copy_mem()函数。movl $0x10,%edx		# set up ds,es to kernel spacemov %dx,%dsmov %dx,%esmovl $0x17,%edx		# fs points to local data spacemov %dx,%fscmpl _NR_syscalls,%eax	#调用号如果超出范围的话就跳转。jae bad_sys_call#下面这句操作数的含义是:调用地址=[_sys_call_table+%eax*4]call _sys_call_table(,%eax,4)	# 间接调用指定功能C函数。pushl %eax						# 把系统调用返回值入栈。#下面的5行查看当前任务的运行状态。如果不在就绪态(state不等于0)就去执行调度程序。#如果该任务在就绪状态,但是其时间片已经用完(counter=0),则也去执行调度程序。#例如当后台进程组中的进程执行控制终端读写操作时,那么默认条件下该后台进程组所有进程会受到#SIGTTIN或SIGTTOU信号,导致进程组中所有进程处于停止状态。而当前进程则会立刻返回。
2:movl _current,%eax			# 读当前任务(进程)数据结构指针->eax。cmpl $0,state(%eax)			# statejne reschedulecmpl $0,counter(%eax)		# counterje reschedule#以下这段代码执行从系统调用C函数返回后,对信号进行识别处理。其他中断服务程序退出时也将跳转#到这里进行处理后才退出中断过程,例如后面131行上的处理器出错中断int 16。#首先判断当前任务是不是初始任务task0,如果是则不必对其进行信号方面的处理,直接返回。#109行上的_task对应C程序中的task[]数组,直接引用task相当于引用task[0]。
ret_from_sys_call:movl _current,%eaxcmpl _task,%eax			# task[0] cannot have signalsje 3f					# 向前(forward)跳转到标号3处退出中断处理。# 通过对原调用程序代码选择符的检查来判断调用程序是不是用户任务。如果不是则直接退出中断。# 这是因为任务在内核态执行时不可抢占。否则对任务进行信号量的识别处理。这里通过比较选择符是否# 为用户代码段的选择符0x000f(RPL=3,局部表,代码段)来判断是否为用户任务。如果不是# 则说明是某个中断服务程序(例如中断16)跳转到第107行执行到此,于是跳转退出中断程序。# 另外,如果原堆栈段选择符部位0x17(即原堆栈不在用户段中),也说明本次系统调用的抵用者# 不是用户任务,则也退出。cmpw $0x0f,CS(%esp)		# was old code segment supervisor ?jne 3fcmpw $0x17,OLDSS(%esp)		# was stack segment = 0x17 ?jne 3f# 下面这段代码用于处理当前任务中的信号。首先取当前任务结构中的信号位图(32位,每位代表1中信号),# 然后用任务结构中的信号阻塞(屏蔽)码,阻塞不允许的信号位,取得数值最小的信号值,# 再把原信号位图中该信号对应的位复位(置0),最后将该信号值作为参数之一调用do_signal()# do_signal()(kernel/signal.c,128)中,其参数包括13个入栈的信息。在do_signal()或信号处理函数返回之后,# 若返回值不为0则再看看是否需要切换进程或继续处理其他信号。movl signal(%eax),%ebx			#取信号位图->ebx,每1位代表1中信号,共32个信号。movl blocked(%eax),%ecx			#取阻塞信号位图->ecx。notl %ecx						#每位取反。ecx=~ecxandl %ebx,%ecx					#获得许可的信号位图。 ecx=ebx&ecxbsfl %ecx,%ecx					#从低位(位0)开始扫描位图,看是否有1的位, 若有,则ecx保留该位的偏移值(即地址为0--31)。je 3f							#如果没有信号则向前跳转退出。btrl %ecx,%ebx					#复位该信号(ebx含有原signal位图)。movl %ebx,signal(%eax)			#重新保存signal位图信号->current->signal。incl %ecx						#将信号调整为从1开始的数(1--32)。pushl %ecx						#信号值入栈作为调用do_signal的参数之一。call _do_signal					#调用C函数信号处理程序(kernel/signal.c,128)。popl %ecx						#弹出入栈的信号值。testl %eax, %eax				#测试返回值,若不为0则跳转到前面标号2处。jne 2b							# see if we need to switch tasks, or do more signals
3:	popl %eax						#eax中含有第100行入栈的系统调用返回值。popl %ebxpopl %ecxpopl %edxaddl $4, %esp					# skip orig_eax #跳过(丢弃)原eax值。pop %fspop %espop %dsiret#int16 -- 处理器错误中断。 类型:错误; 无错误码。
#这是一个外部的基于硬件的异常。当协处理器检测到自己发生错误是,就会通过ERROR引脚
#通知CPU。下面代码用于处理协处理器发出的出错信号。并跳转去执行C函数math_error()
#(kernel/math/error.c 11)。返回后将跳转到标号ret_from_sys_call处继续执行。
.align 2
_coprocessor_error:push %dspush %espush %fspushl $-1				# fill in -1 for orig_eax #填-1,表明不是系统调用。pushl %edxpushl %ecxpushl %ebxpushl %eaxmovl $0x10,%eax				#ds,es置为指向内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax				#fs置位指向局部数据段(出错程序的数据段)。mov %ax,%fspushl $ret_from_sys_call	#把下面调用返回地址入栈。jmp _math_error				#执行math_error()(kernel/math/error.c,11)#int7 -- 设备不存在或协处理器不存在。 类型:错误;无错误码。
#1、如果控制寄存器CR0中EM(模拟)标志置位,则当CPU执行一个协处理器指令时就会引发该中断,
#这样CPU就可以有机会让这个中断处理程序模拟协处理器指令(call _math_emulate)。
#2、CR0的 交换标志TS是在CPU执行任务转换时设置的。TS可以用来确定什么时候协处理器中的内容
#与CPU正在执行的任务不匹配了。当CPU在运行一个协处理器转移指令时发现TS置位时,就会引发
#该中断。此时就可以保存前一个任务的协处理器内容,并恢复新任务的协处理器执行状态(_math_state_restore)。
#参见kernel/sched.c,92行。该中断最后将转移到标号ret_from_sys_call处执行下去(监测并处理信号)。
.align 2
_device_not_available:push %dspush %espush %fspushl $-1				# fill in -1 for orig_eax #填-1,表明不是系统调用。pushl %edxpushl %ecxpushl %ebxpushl %eaxmovl $0x10,%eax			#ds,es置为指向内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax			#fs置位指向局部数据段(出错程序的数据段)。mov %ax,%fs#清CR0中任务已交换标志TS,并取CR0值。若其中协处理器仿真标志EM没有置位,说明不是#EM引起的中断,则恢复任务协处理器状态,指向C函数math_state_restore(),并在返回时#去执行ret_from_sys_call处的代码。pushl $ret_from_sys_call		#把下面跳转或调用的返回地址入栈。clts							# clear TS so that we can use math (清除TS,以便我们可以用软件协处理器。)^_^linus大神当时机器没有硬件协处理器movl %cr0,%eaxtestl $0x4,%eax					# EM (math emulation bit)je _math_state_restore			#执行math_state_restore()(kernel/sched.c,92)。#若EM标志置位,则去执行数学仿真程序math_emulate()。pushl %ebppushl %esipushl %edipushl $0						# temporary storage for ORIG_EIPcall _math_emulate				#调用C函数(math/math_emulate.c,476)。addl $4,%esp					#丢弃临时存储。popl %edipopl %esipopl %ebpret								#int32 -- (int 0x20)时钟中断处理程序。中断频率设置为100Hz(include/linux/sched.h,4),
#定时芯片8253/8254实在(kernel/sched.c,438)处初始化的。因此这里jiffies每10毫秒加1。
#这段代码将jiffies增1,发送结束中断指令给8259控制器,然后用当前特权级作为参数调用C函数
#do_timer(long CPL)。当调用返回时跳转检查并处理信号。
.align 2
_timer_interrupt:push %ds		# save ds,es and put kernel data spacepush %es		# into them. %fs is used by _system_callpush %fs		# 保存ds、es并让其指向内核数据段。fs将用于system_call。pushl $-1		# fill in -1 for orig_eax #填-1,表明不是系统调用。#下面我们保存寄存器eax、ecx和edx。这是因为gcc编译器在调用函数时不会保存他们。#这里也保存了ebx寄存器,因为在后面ret_from_sys_call中会用到它。pushl %edx		# we save %eax,%ecx,%edx as gcc doesn'tpushl %ecx		# save those across function calls. %ebxpushl %ebx		# is saved as we use that in ret_sys_callpushl %eaxmovl $0x10,%eax		#de,es置为指向内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax		#fs置为指向局部数据段(程序的数据段)。mov %ax,%fsincl _jiffies#由于初始化中断控制芯片时乜有采用自动EOI,所以这里需要发指令结束该硬件中断。movb $0x20,%al		# EOI to interrupt controller #1outb %al,$0x20#下面从堆栈中取出指向系统调用代码的选择符(CS段寄存器值)中的当前特权级(03)并压入堆栈,#作为do_timer的参数。do_timer()函数执行任务切换、计时等工作,在kernel/sched.c,324行实现。movl CS(%esp),%eaxandl $3,%eax		# %eax is CPL (0 or 3, 0=supervisor)pushl %eaxcall _do_timer		# 'do_timer(long CPL)' does everything fromaddl $4,%esp		# task switching to accounting ...jmp ret_from_sys_call#这是sys_execve()系统调用。取中断调用程序需的代码指针作为参数调用C函数do_execve().
#do_execve()在fs/exec.c,207行。
.align 2
_sys_execve:lea EIP(%esp),%eax	#eax指向堆栈中保存用户程序eip指针处。pushl %eaxcall _do_execveaddl $4,%esp		#丢弃调用时压入栈的EIP值。ret#sys_fork()调用,用于创建子进程,是system_call功能2。原形在include/linux/sys.h中。
#首先调用C函数find_empty_process(),取得一个进程号last_pid。
#若返回负数则说明目前任务数组已满。然后调用copy_process()复制进程。
.align 2
_sys_fork:call _find_empty_process		#为新进程取得进程号last_pid。(kernel/fork.c,143)。testl %eax,%eax					#在eax中返回进程号。若返回负数则退出。js 1fpush %gspushl %esipushl %edipushl %ebppushl %eaxcall _copy_process				#调用C函数copy_process()(kernel/fork.c,68)。addl $20,%esp					#丢弃这里所有压栈内容。
1:	ret#int 46 -- (int 0x2E)硬盘中断处理程序,响应硬件中断请求IRQ14。
#当请求的硬盘操作完成或出错就会发出此中断信号。(参见kernel/blk_drv/hd.c)。
#首先想8259A中断控制从芯片发送结束硬件中断指令(EOI),然后取变量do_hd中的函数指针放入edx
#寄存器中,并置do_hd为NULL,接着判断edx函数指针是否为空。如果为空,则给edx赋值指向
#unexpected_hd_interrupt(),用于显示出错信息。随后想8259A主芯片发送EOI指令,并调用edx中
#指针指向的函数:read_intr(0write_intr()unexpected_hd_interrupt()。
_hd_interrupt:pushl %eaxpushl %ecxpushl %edxpush %dspush %espush %fsmovl $0x10,%eax				#ds,es置为内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax				#fs置为调用程序的局部数据段。mov %ax,%fs#由于初始化中断控制芯片时没有采用自动EOI,所以这里需要发指令结束该硬件中断。movb $0x20,%aloutb %al,$0xA0				# EOI to interrupt controller #1 	#送从8259A。jmp 1f						# give port chance to breathe		#这里jmp起延时作用。
1:	jmp 1f
#do_hd定义为一个函数指针,将被赋值read_intr()write_intr()函数地址。放到edx寄存器后
#就将do_hd指针变量置为NULL。然后测试得到的函数指针,若该指针为空,则赋予该指针指向C函数
#unexpected_hd_interrupt(),以处理未知硬盘中断。
1:	xorl %edx,%edxmovl %edx,_hd_timeout		#hd_timeout置为0.表示控制器已在规定时间内产生了中断。xchgl _do_hd,%edxtestl %edx,%edxjne 1f						#若空,则让指针指向C函数unexpected_hd_interrupt()。movl $_unexpected_hd_interrupt,%edx
1:	outb %al,$0x20				#送8259A主芯片EOI指令(结束硬件中断)。call *%edx					# "interesting" way of handling intr. 上局调用do_hd指向的C函数。pop %fs						pop %espop %dspopl %edxpopl %ecxpopl %eaxiret#int32 -- (int 0x26)软盘驱动器中断处理程序,响应硬件中断请求IRQ6。
#器处理过程与上面对硬盘的处理基本一样。(kernel/blk_drv/floppy.c)。
#首先向8259A中断控制器主芯片发送EOI指令,然后取变量do_floppy中的函数指针放入eax寄存器中,
#并置do_floppy位NULL,接着判断eax函数指针是否为空。如为空,则给eax赋值指向unexpected_floppy_interrupt(),
#用于显示出错信息。随后调用eax指向的函数:
#rw_interrupt,seek_interrupt,recal_interrupt,reset_interrupt或unexpected_floppy_interrupt。
_floppy_interrupt:pushl %eaxpushl %ecxpushl %edxpush %dspush %espush %fsmovl $0x10,%eax				#de,es置为内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax				#fs置为调用程序的局部数据段。mov %ax,%fsmovb $0x20,%al				#送主8259A中断控制器EOI指令(结束硬件中断)。outb %al,$0x20				# EOI to interrupt controller #1xorl %eax,%eax#do_floppy为函数指针,将被赋值实际处理C函数指针。#该指针在被交换放到eax寄存器后就将do_floppy变量置空。#然后测试eax中原指针是否为空若是则使指针指向C函数unexpected_floppy_interrupt()xchgl _do_floppy,%eaxtestl %eax,%eax						#测试函数指针是否=NULL?jne 1f								#若空,则使指针指向C函数unexpected_floppy_interrupt()。movl $_unexpected_floppy_interrupt,%eax
1:	call *%eax							# "interesting" way of handling intr. #上局调用do_floppy指向的函数。pop %fspop %espop %dspopl %edxpopl %ecxpopl %eaxiret#int39 -- (int 0x27)并行口中断处理程序,对应硬件中断请求信号IRQ7。
#本版本内核还未实现。这里只是发送EOI指令。
_parallel_interrupt:pushl %eaxmovb $0x20,%aloutb %al,$0x20popl %eaxiret

8-4-3 其他信息

1、 GUN汇编语言的32位寻址方式

GNU汇编语言采用的是AT&T的汇编语言语法。32位寻址的规则格式为:
AT&T: immed32(basepointer,indexpointer,indexscale)
Inter:[basepointer+indexpointerindexscale+immed32]
(1)对一个指定的C语言变量寻址:
AT&T: _booga
Inter: [_booga]
(2)对寄存器内容指向的位置寻址:
AT&T: (%eax)
Inter: [eax]
(3)通过寄存器中的内容作为基址寻址一个变量:
AT&T: _variable(%eax)
Inter: [eax+_variable]
(4)在一个整数数组中寻址一个值(比例值为4):
AT&T: _array(,%eax,4)
Inter: [eax
4+_array]
(5)使用直接数寻址偏移量:
对于C语言:(p+1)其中p是字符的指针char
AT&T: 1(%eax)其中eax中时p的值。
Inter: [eax+1]
(6)在一个8字节为一个记录的数组寻址指定的字符。其中eax中时指定的记录号,
ebx中时指定字符在记录中的偏移址:
AT&T: _array(%ebx,%eax,8)
Inter: [ebx+eax*8+_array]

2、 增加系统调用功能

(1)在kernel/sys.c添加系统的底层函数sys_sethostname
(2)在include/unistd.h文件中增加新系统调用功能号和原型定义。

#define __NR_sethostname 72
int sethostname(char *name,int len);

(3)在include/linux/sys.h文件中加入外部函数声明并
在函数指针表sys_call_table末端插入新系统调用处理函数的名称。

extern int sethostname(char *name,int len);
fn_ptr sys_call_table[] = {……,sethostname};

(4)修改sys_call.s程序 nr_system_calls = 82
改nr_system_calls = 83
(5)参照lib/目录下库函数的实现方法在libc库中国增加新的系统调用库函数sethostname

#define __LIBRARY__
#include <unistd.h>
_syscall2(int,sethostname,char *,name,int,len)

3、 在汇编程序中直接使用系统调用

.text
_entru:movl $4,%eax			#系统调用号,写操作。movl $1,%ebx			#写调用的参数,是文本描述符。数值1对应标准输出stdout。movl $message,%ecx		#参数,缓冲区指针。movl $12,%edx			#参数,写数据长度(数数下面字符串的长度(-:)。int $0x80movl $1,%eax			#系统调用号,退出程序。int $0x80
message:.ascii "Helllo World\n"

运行结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_484520.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JVM】面试题总结

JVM 1、JVM 的运行时内存区域是怎样的2、堆和栈的区别3、Java 中的对象一定在堆上分配内存吗4、什么是 Stop The World5、JVM 如何判断对象是否存活6、JVM 有哪些垃圾回收算法7、什么是三色标记算法8、新生代和老年代的GC算法9、新生代和老年代的垃圾回收器有何区别10、Java 中…

MYSQL用户组管理

1&#xff1a;使用明文密码创建用户 使用密文密码创建用户 1.2 查看用户信息 1.3 重命名用户 rename 1.4 删除用户信息 drop 1.5 修改当前登录用户的密码 set password password(123456); 1.6 修改其他用户的密码 set password for nancylocalhost password(abc123); 1.7…

电子价签能给生鲜零售带来什么?

生鲜零售 变价难 超市中的水果、蔬菜、鱼肉海鲜等商品&#xff0c;往往会受季节变化、运输和储存成本、自然环境引起的生产成本、供需关系等因素影响&#xff0c;其商品价格变动比较频繁。如不能及时更新价格&#xff0c;容易影响商品的销售&#xff0c;进而影响超市的盈利能…

【致敬未来的攻城狮计划】第2期定向赠书《RT-Thread设备驱动开发指南》+ 《GD32 MCU原理及固件库开发指南》

开启攻城狮的成长之旅&#xff01;这是我参与的由 CSDN博客专家 架构师李肯&#xff08;超链接&#xff1a;http://yyds.recan-li.cn&#xff09;和 瑞萨MCU &#xff08;超链接&#xff1a;瑞萨电子 (Renesas Electronics Corporation)&#xff09; 联合发起的「 致敬未来的攻…

测试用例覆盖不全面的解决方法

测试用例覆盖不全面的解决方法 问题分析 在测试用例设计过程中&#xff0c;容易出现思维受限或者需求盲区&#xff0c;我们不可能完全覆盖用户使用的所有场景&#xff0c;编写测试用例的时不可能把所有的场景都能想周全&#xff0c;把所有的场景下的情况都写成测试用例去模拟、…

儿童书写台灯哪个牌子比较好?盘点护眼学生用台灯品牌排行

想要拥有一个健康的视力对于我们多么重要&#xff0c;日常生活多么不便利&#xff0c;就是像家里孩子考学时视力也是对于未来专业选择的一个阻碍。 想要孩子不吃近视的苦&#xff0c;从小就要开始抓孩子对于视力和眼睛的呵护。 养成好习惯必须保持一个正确的学习姿势&#xff…

基于pytorch+transformers的车牌识别

目录 程序流程设计熟悉训练数据集CCPD2019数据集CCPD数据集标注信息单例再现 加载本地车牌数据集 程序流程设计 1&#xff0c;熟悉训练数据集&#xff1b; 2&#xff0c;加载本地车牌数据集&#xff1b; 3&#xff0c;定义网络模型&#xff1b; 4&#xff0c;输入数据集训练模…

Baumer工业相机堡盟工业相机如何联合BGAPISDK和Halcon实现图像的线性灰度变换ScaleImage算法增强(C#)

Baumer工业相机堡盟工业相机如何联合BGAPISDK和Halcon实现图像的线性灰度变换算法增强&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机使用图像算法增加图像的技术背景Baumer工业相机通过BGAPI SDK联合Halcon使用线性灰度变换增强算法1.引用合适的类文件2.BGAPI SDK在…

「STC8A8K64D4开发板」——外部中断(INT0~INT4)

第2-4讲&#xff1a;外部中断(INT0~INT4) 学习目的学习中断的相关概念。掌握外部中断配置及中断优先级配置的程序设计。掌握中断服务程序的编写。 中断相关概念 什么是中断 中断系统是为使 CPU 具有对外界紧急事件的实时处理能力而设置的。 CPU在处理某一事件A时&#xff0c…

基于YOLOv5的儿童睡眠检测

注意&#xff1a; 由于SOPHGO SE5微服务器的CPU是基于ARM架构&#xff0c;部分步骤将在 基于x86架构CPU的开发环境中完成 一、初始化开发环境(基于x86架构CPU的开发环境中完成) 二、模型转换 (基于x86架构CPU的开发环境中完成) 三、YOLOv5模型部署测试&#xff08;在SOPHGO SE5…

超细Redis(一)

目录 概述 Redis是什么&#xff1f; Redis能干嘛&#xff1f; 特性 如何学习 Linux安装 测试性能 概述 Redis是什么&#xff1f; Redis &#xff08;Remote Dictionary Server&#xff09;,即远程字典服务 是一个开源使用ANSI C语言编写、支持网络、可基于内存亦可持…

【SVN】版本控制管理的文件(夹)如何重命名

目录 一、前言二、操作步骤1. 使用SVN重命名&#xff08;SVN rename&#xff09;2. 输入新名称3. 确定重命名4. 立刻进行一次提交&#xff08;commit&#xff09;5. 补充 三、可能遇到的问题1. 情况一2. 情况二3. 情况三 一、前言 如果只是在本地的文件系统中修改SVN中的文件&a…

STM32CUBEMX 待机模式最简单的RTC定时唤醒(低功耗电池产品必备)

文章意义&#xff1a; 看到很多技术帖子讲述RTC定时唤醒功能的时候&#xff0c;老是需要去读取当前时间&#xff0c;再设定下一个闹钟唤醒时间&#xff0c;无形中多了很多变量和操作。所以我决定分享一种简单的RTC定时唤醒方法&#xff0c;适合于不需要实现具体时间获取的场合…

K8s基础3——应用部署流程、服务编排、集群资源利用率、日志管理

文章目录 一、应用部署流程二、服务编排2.1 YAML文件格式说明2.2 部署应用2.2.1 命令部署2.2.2 yaml文件部署2.2.2.1 编写deployment.yaml文件2.2.2.2 编写service.yaml文件2.2.2.3 两个yaml文件混用2.2.2.4 测试——service和deployment的标签不一致导致访问网页混乱 2.2.3 自…

04-菜单维护 尚筹网

在【菜单维护】页面&#xff0c;通过树形结构&#xff0c;使用zTree显示整个菜单。 准备工作 一、在数据库创建菜单表&#xff1a; #使用project_rowd表 use project_rowd;#创建菜单的数据库表 create table t_menu (id int(11) not null auto_increment, pid int(11), nam…

openEuler RISC-V 成功适配 LicheePi 4A 开发板,推动 RISC-V 生态发展

近期&#xff0c;RISC-V SIG 在 LicheePi 4A 开发板上成功实现了欧拉操作系统的适配。目前&#xff0c;最新版本的 openEuler RISC-V 23.03 V1 镜像已在 LicheePi 4A 开发板上可用&#xff0c;这一成果再次展现了 openEuler 在推动 RISC-V 生态发展过程中所取得的新突破。 下载…

黑马在线教育数仓实战9

2.6 数据清洗转换操作 ​ 目的: 主要是用于从ODS以及DIM层 将数据灌入到DWM层操作 生成学生出勤状态信息表 涉及表: course_table_upload_detail: 日志课程明细表 (课表) (维度表) tbh_student_signin_record: 学生打卡记录表 (事实表) tbh_class_time_ta…

FL Studio21最新中文版本下载及详细安装教程

FL Studio21最新中文版本是一款专业的音乐制作软件&#xff0c;软件支持录音、音频剪辑、混音、编曲等众多实用功能&#xff0c;可以让你的电脑化身为专业的录音室&#xff0c;进行音乐的录制和剪辑工作&#xff0c;帮助用户轻松创作出各种优秀的音乐作品。 FL Studio21中文版…

第4章-动态规划

第4章-动态规划 总分&#xff1a;100分 得分&#xff1a;100.0分 10.0 分 1 . 多选题 中等 10分 有关0-1背包问题,用c[i][j]描述子问题:1...i共i个物品,背包容量为j的最优值(装入背包的最大价值),则其子问题为:1...i-1共i-1个物品,背包容量为j-w ix i,以下说法正确的是( AB…

Linux搭建我的世界服务器 + 公网远程联机教程「不需要公网IP」

文章目录 前言1. 安装JAVA2. MCSManager安装3.局域网访问MCSM4.创建我的世界服务器5.局域网联机测试6.安装cpolar内网穿透7. 配置公网访问地址8.远程联机测试9. 配置固定远程联机端口地址9.1 保留一个固定tcp地址9.2 配置固定公网TCP地址9.3 使用固定公网地址远程联机 转载自内…