2019-2020-5 20199317 "Linux kernel principle and Analysis" in the fifth week of work

Three-tier mechanism (on) Chapter 4 system calls

1 user mode, kernel mode and interrupt

        Most programmers hard to leave the system call when writing a program, call dealing with the system is by way of library functions, library functions for the system call to package together.

       Computer hardware resources are limited, conflict in order to reduce access and use of limited resources, CPU and operating system must provide some mechanism for the user program division of authority. Then there is the user mode and kernel mode, executed at a high level code can execute a privileged instruction, access to any physical memory, CPU time is performed corresponding to the level kernel mode, privileged instructions comprising all instructions to be carried out. Accordingly, in the user state (low-level instructions), the code can grasp the scope is limited.

       Intel x86 CPU There are four different levels of implementation, namely 0,1,2,3, the smaller the number, the higher the privilege. Linux operating system, which only uses the two privilege levels 0 and 3, corresponding to the kernel mode and user mode.

       A very significant discrimination method is a user mode and kernel mode CS: EIP point range, when the kernel mode, CS: EIP values ​​may be arbitrary address, and in the user mode, this value is restricted.

       The system is also a call to interrupt (interrupt processing is the main way into the kernel mode from user mode). In general, the kernel mode is triggered by an interrupt, hardware interrupt may be, it could be during user program execution state, called a system call into a kernel mode (system calls only special interrupt called Trap ).

       When switched to the user mode kernel mode, user mode register context it should be saved, while the value of the register is put into the kernel-mode current CPU. int instruction triggers an interrupt mechanism saves the values ​​of some registers on the stack, the stack will save user mode address, then the status word, then CS: EIP's value. While the top of the stack will address kernel mode, the kernel mode status word into the corresponding CPU registers, and CS: EIP register value to the interrupt handler entry point for the system call is concerned system_call.

       Process interrupts: Linux is done by the system call interrupt int 0x80, saving the user mode interrupt CS: EIP the top of the stack and the current stack segment registers save the current value of the EFLAGS register of the stack to the kernel, while entrance interrupt service routine of the current interrupt signal or system call is loaded into CS: EIP years, the current stack segment SS: ESP also be loaded into the CPU, these are signals or int instruction is done by the interruption. Upon completion, the current CPU when executing the next instruction has already begun to execute the interrupt handler entrance, and then the operation of the stack is already operating a kernel stack, before SAVE_ALL is the kernel code, an interrupt service is completed, the process of scheduling occurs, directly restore_all resume the interrupted scene, iret then return to its original state; if the process scheduling occurs, the current state of these will be temporarily stored in the system and kernel stack, the process of scheduling the next time occurrence, and will be followed by the restore_all iret executed, this is the entire interrupt processing.

Overview 2 System calls

        System call is (trap way) by issuing software interrupt interrupt request to the kernel, int instruction execution will trigger an interrupt request.

       Usually the package corresponding to each system call routines, a system library calls routines use these packages define the API call to the programmer so that the final package system calls to library functions programmers to use.

       API libc provide may provide some direct user-mode service, it does not need to deal with the kernel through system calls, such as some mathematical functions, etc., but relate to the interaction with the kernel API internal space of the packaging system will call. An API may correspond to only a system call may also be a plurality of internal system call, the system call may also be a plurality of API calls. It does not involve interaction with the kernel API calls inside the packaging system does not, for example, the mathematical absolute value function abs ().

       For the return value, most of the packaging system call routine returns an integer value whose meaning depends on the corresponding system call, the kernel returns a value of -1 indicates the process can not satisfy the request, in most cases, it is further defined in the libc errno variable It contains a specific error code.

       All in all, 3-layer mechanism system calls for: API, interrupt vector, the interrupt service routine.

       When a user mode process calls a system call, CPU switching to kernel mode and begin executing a system call kernel functions and system_call. In Linux through execution int $ 0x80 to trigger a system call, this assembly instructions generate an interrupt vector is programmed 128 exception. After entering the kernel starts executing the interrupt vector 128 corresponding interrupt service routine system_call, Linux operating system, there are about 200 system calls in the kernel here to differentiate by calling a number to each system, that system call number, the API function xyz ( ) and system calls the kernel function sys_xyz () linked up. Kernel implements many different system calls, user mode processes must indicate which system needs to call, which requires the use EAX register parameter passing a named system call number. In addition to the system call number, the call might need to pass the system parameters, the function call is normal by the pushing of the parameters passed by. System call is switched from user mode to kernel mode, used in two execution modes is different stack, i.e., user mode and kernel mode process stack process, the method to pass parameters via the parameter can not push manner, but by comparing special mode register transmission parameters. In addition to the number of delivery systems for EAX call number, the parameter assigned to EBX, ECX, EDX, ESI, EDI, EBP, of the order parameter is not more than 6, i.e., the six registers. If one took over six register as a pointer to memory, so more parameters can be passed through the memory.

3 API library functions using C code and assembly code embedded in the same system call trigger

      Write a time.c program:

      Use the library function triggers a system call API

       

       

       C code embedded assembler code triggers a system call:

        

        

        Examples of system calls containing two parameters

       Here we will achieve hello.c file rename newhello.c, modify the return value of 0 indicates success.

       First use the API library functions to trigger rename system call , the system call rename function is to rename a file, as shown below:

        

        

        The next step is embedded assembly code to trigger rename system call , as shown below:

        

        

       在这里出现了一个问题:我用“gcc rename_asm.c”命令编译时出现了错误“ Error:unsupported instruction 'mov' ”,然后我使用“ gcc rename_asm.c -o rename_asm -m32 ”命令就编译成功,这是因为32位汇编代码对应的是movl。

       然后这段汇编代码的意思为:把系统调用号38(16进制是0x26)存入EAX寄存器,将oldname存入EBX寄存器,将newname存入ECX寄存器,通过执行int $0x80来执行系统调用陷入内核态。system_call根据传入的系统调用号在系统调用列表中查找到对应的系统调用内核函数,然后根据EBX寄存器和ECX寄存器中保存的参数调用内核函数sys_rename,执行完后将执行结果存放到EAX寄存器中,将EAX寄存器的值传给ret。

       接下来将“=a”换成“=m”,得到如下图所示结果:

        

        可以看到hello.c确实变成了newhello.c,却显示没有修改成功。hello.c变成newhello.c,表示确实执行了sys_rename,返回值0保存在EAX寄存器中。显示失败是指ret不等于0。

       通用的触发系统调用的库函数syscall

       如果libc没有提供对某个系统调用的封装,就无法通过API方法来调用内核函数,或者说内核增加了一个新的系统调用,但libc函数库的版本没有及时更新为其编写API函数,这种情况下我们就可以利用libc提供的syscall函数直接调用,函数原型为:extern long int syscall(long int sysno,...) _THROW,其中sysno是系统调用号,“...”是系统调用所带的参数。如下图所示:

         

         这里将SYS_rename改为38也可以实现。

         

4  总结

      在本次实验中,我初步了解到了一些关于系统调用的工作机制,比如系统调用可以用API函数直接调用或者在C语言中嵌入汇编代码来进行调用,但是两者都需要使用系统调用号,不同的是API函数已经把系统调用号封装起来了,与内核系统调用形成了映射关系。

      

      

 

 

 

    

 

 

 

 

     

 

 

 

     

 

 

 

 

       

 

     

      

        

     

    

Guess you like

Origin www.cnblogs.com/chengzhenghua/p/11697837.html