System Call (ii)

Source: Internet
Author: User

(v): implementation of system calls

1: Implement system call

The implementation of a system call is to consider his purpose, each system call has a definite purpose, in Linux does not advocate the use of multi-purpose system calls (a system call by passing different parameters to choose to complete the different work).

2: Validation of references

System calls must be carefully checked to see if all of their parameters are valid. One of the most important checks is to check that the user-supplied pointer is valid.
Before a pointer to a user space is received. The kernel must ensure that:



The kernel provides two methods to complete the necessary checks and a back-and-forth copy of the data between the kernel space and the user space.

In order to write data to the user space, the kernel provides copy_to_user (), which requires three parameters, and the first parameter is the destination memory address in the process space. The second is the source address within the kernel space, and the third parameter is the length (in bytes) of the data that needs to be copied.

In order to read data from the user space. The kernel provides copy_from_user (), which is similar to Copy_to_user (), which copies the data at the specified position in the second parameter to the location specified by the first parameter, and the length of the copied data is specified by the third parameter.

Assuming that the run fails, both functions return the number of bytes of data that were not able to complete the copy. Assume success. Then 0 is returned. When the above error occurs, the system call returns the standard-efault.

Here we look at a sample, silly_copy () function.

/* * silly_copy no real value for system calls. He copies the Len byte data from the ' src ' copy of ' DST ', which makes the kernel space a stopover for no reason. 

*/systemcall_define3 (silly_copy, unsigned long *src, unsigned long *dst, unsigned l Ong len) {unsigned long buf; /* Copy src from user address into DST */if (Copy_from_user (&buf,src,len)) return -efault; /* copies the BUF into the DST */ in the user address space if (Copy_to_user (Dst,&buf,len)) return -efault; /* returns the amount of data copied */ return len;}

Note that both the Copy_to_user () and the Copy_from_user () functions can cause clogging.

When a page that includes user data is swapped out on the hard disk instead of in physical memory. This happens, at this point. The process will hibernate. Know that the page-fault handler swapped the pages from the hard disk back to physical memory.

The last item is to check for legitimate permissions. In today's Linux system. The ability to use the capable () function to check for permissions on a specified resource process operation. If a value other than 0 is returned, the caller is entitled to the process operation. return 0 means no permission to operate.

Let's take a look at the use of the capality () function in the reboot system call.

/* * Reboot system call: for obvious reasons only root may call it, * and even root needs to set up some magic numbers in the registers * so that some mistake won‘t make this reboot the whole machine. * You can also set the meaning of the ctrl-alt-del-key here. * * reboor系统调用:因为一些显著的原因,只root用户才干调用他。

* Even the root user will need to set some parameters in the register. So some errors will not cause the whole machine to restart. * * Reboot doesn ' t sync:do that yourself before calling this. * * Reboot is not collaborative: do those things yourself before calling this. */Syscall_define4 (reboot,int, Magic1,int, Magic2, unsignedintCmdvoid__user *, Arg) {Charbuffer[ the];intRET =0;/ * We only trust the Superuser with rebooting the system. * / / * We only trust the Power user who started the system * / if(!capable (Cap_sys_boot))return-eperm;/ * For safety, we require "magic" arguments. * / / * For security reasons, we need a "magic" number * * if(Magic1! = Linux_reboot_magic1 | | (Magic2! = Linux_reboot_magic2 && Magic2! = linux_reboot_magic2a && Magic2! = LINUX_REBOOT_MAGIC2B && Magic2! = linux_reboot_magic2c))return-einval;/* Instead of trying to make the Power_off code look like * halt when pm_power_off are not set does it the easy . * * When the Pm_power_off is not set. Please do not try to make Power_off code * look like it is able to stop, but should be used in a simpler way * * if(cmd = = linux_reboot_cmd_power_off) &&!pm_power_off) cmd = Linux_reboot_cmd_halt; Mutex_lock (&reboot_mutex);Switch(CMD) { CaseLinux_reboot_cmd_restart:kernel_restart (NULL); Break; CaseLinux_reboot_cmd_cad_on:c_a_d =1; Break; CaseLinux_reboot_cmd_cad_off:c_a_d =0; Break; CaseLinux_reboot_cmd_halt:kernel_halt (); Do_exit (0); Panic"Cannot halt"); CaseLinux_reboot_cmd_power_off:kernel_power_off (); Do_exit (0); Break; CaseLinux_reboot_cmd_restart2:if(Strncpy_from_user (&buffer[0], ARG,sizeof(buffer)-1) <0) {ret =-efault; Break; } buffer[sizeof(buffer)-1] ="'; Kernel_restart (buffer); Break;#ifdef config_kexec CaseLinux_reboot_cmd_kexec:ret = Kernel_kexec (); Break;#endif #ifdef config_hibernation CaseLinux_reboot_cmd_sw_suspend:ret = Hibernate (); Break;#endif default: ret =-einval; Break; } mutex_unlock (&reboot_mutex);returnRET;}

The first is to determine whether the calling process has Cap_sys_reboot rights. In the Linux/capality.h file, include a list of all these permissions and the appropriate permissions. Let's look at it a little bit:

/** * * Posix-draft defined capabilities. **//* in a system withThe [_posix_chown_restricted] option defined, ThisOverrides the restriction ofchanging file ownership andGroup ownership. */#define CAP_CHOWN 0/* Override all DAC access, including ACL Execute accessif[_posix_acl] isDefined. Excluding DAC access covered byCap_linux_immutable. */#define Cap_dac_override 1/* Overrides All DAC restrictions regarding read andSearch onFiles anddirectories, including ACL restrictionsif[_posix_acl] isDefined. Excluding DAC access covered byCap_linux_immutable. */#define Cap_dac_read_search 2/* Overrides All restrictions about allowed operations onfiles, where file owner ID must is equal to the user ID, except where Cap_fsetid isApplicable. It doesn' t override MAC and DAC restrictions. */#define Cap_fowner 3// .....

(vi): System call Context

In the above. We know that when the process system is called, it is handled by the Sys_call () process, and the control is still in the hands of System_call () when the system is called and returned. He will finally be responsible for switching to user space and allowing the user process to continue running.

1: Last step of binding a system call
When writing to play a system call, it is tedious to register him as a formal system call:


First we invent a system call Foo (). To use these steps.

The Sys_foo system call is first added to the last table entry in the calling table, which is located in the Kernel/syscall_table_32.s file.

ENTRY (sys_call_table).LongSys_restart_syscall/* 0-old "setup ()" System call, used for restarting */.LongSys_exit.LongPtregs_fork.LongSys_read.LongSys_write.LongSys_open/ * 5 * /.LongSys_close.LongSys_waitpid.LongSys_creat.LongSys_link.LongSys_unlink/ * Ten * /// ...............................................LongSys_rt_tgsigqueueinfo/ * 335 * /.LongSys_perf_event_open.LongSys_recvmmsg.LongSys_foo/ * 338 * /

It is very obvious that the system call number of our system call is 338.

This system invocation is architecture-related. So it needs to be placed in the appropriate architecture file.

Secondly. We add the system call number to the Asm/unistd.h file.

#define __NR_rt_tgsigqueueinfo 240__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)#define __NR_perf_event_open 241__SYSCALL(__NR_perf_event_open, sys_perf_event_open)#define __NR_accept4 242__SYSCALL(__NR_accept4, sys_accept4)#define __NR_recvmmsg 243__SYSCALL(__NR_recvmmsg, sys_recvmmsg)#undef __NR_syscalls#define __NR_syscalls 244#define _NR_foo 338

Finally, implement the system call function foo (). Depending on the functions of the function. We can put in the relevant file, this Foo () function I put into the kernel/sys.c file.

#include <asm/page.h>/*  * sys_foo -返回内核栈的大小 * */long sys_foo(void){    return THREAD_SIZE;}

This enables the kernel to be started and called by the Foo () system in user space.

2: Access to system calls from user space

The Linux kernel provides a macro to invoke the system call in the user space, and here's how to test the previous foo () system call

#define _NR_foo 338__syscall0(long,foo)int main(){    long stack_size;    stack_size = foo();    printf("The kernel stack size is %ld.",stack_size);    return0;}

Among them, #define _NR_FOO 338 represents the system call number for the Foo system call
__syscall0 (Long,foo): 0 indicates that 0 arguments are passed to the Foo system, which represents the number of parameters passed to the system call.

3: Why not implement the system call method

First, let's look at the advantages of the system call:


Problems with system calls:


System Call (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.