深入浅出的Linux系统调用

一、系统调用是什么?

       Linux内核为用户态程序提供的主要功能接口。通过系统调用,用户态进程能够临时切换到内核态,访问系统资源

二、为什么要系统调用?

       由于系统有限的资源可能被多个不同的应用程序同时访问,如果不加以保护,那么各个应用程序难免会产生冲突。所以一种解决方法是,不让应用程序直接访问系统的资源,所以增加了一层中间接口,那就是系统调用。

三、系统调用的过程,以open(Linux x86)为例讲解

    1、应用程序调用open时,进程会调用C库中open的实现

    2、C库中open的实现会将open的系统调用号保存在寄存器中(eax)中

    3、通过汇编指令 int 0x80 触发软中断

    4、程序跳到了系统调用处理程序的入口:system_call()

    5、system_call()检查系统调用号(存放在eax中),告诉内核进程请求那种服务

    6、查看系统调用表(system_call_table)找到系统调用服务例程

    7、执行相应的函数,执行完毕后原路返回

四、如何添加一个系统调用?

    1、添加系统调用的内核实现

        在 kernel/arch/arm/kernel/sys_arm.c 文件中添加新系统调用的内核实现sys_add

        已有的系统调用内核实现:

	asmlinkage int sys_fork(struct pt_regs *regs)
	{
	#ifdef CONFIG_MMU
		return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
	#else
		return(-EINVAL);
	#endif
	}

	asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
			 int __user *parent_tidptr, int tls_val,
			 int __user *child_tidptr, struct pt_regs *regs)
	{
		if (!newsp)
			newsp = regs->ARM_sp;
		return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
	}

	asmlinkage int sys_vfork(struct pt_regs *regs)
	{
		return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
	}

        添加新的系统调用内核实现:

	void sys_add(int x, int y)
	{
		return ((x)+(y));
	}

    2、按格式要求添加新的的系统调用号

        在 kernel/arch/arm/include/asm/unistd.h 中添加一个新的系统调用号

        已有的系统调用号:

	#define __NR_restart_syscall		(__NR_SYSCALL_BASE+  0)
	#define __NR_exit			(__NR_SYSCALL_BASE+  1)
	#define __NR_fork			(__NR_SYSCALL_BASE+  2)
	#define __NR_read			(__NR_SYSCALL_BASE+  3)
	#define __NR_write			(__NR_SYSCALL_BASE+  4)
	#define __NR_open			(__NR_SYSCALL_BASE+  5)
	#define __NR_close			(__NR_SYSCALL_BASE+  6)
					/* 7 was sys_waitpid */
	#define __NR_creat			(__NR_SYSCALL_BASE+  8)
	#define __NR_link			(__NR_SYSCALL_BASE+  9)
	#define __NR_unlink			(__NR_SYSCALL_BASE+ 10)
	#define __NR_execve			(__NR_SYSCALL_BASE+ 11)
	#define __NR_chdir			(__NR_SYSCALL_BASE+ 12)
	#define __NR_time			(__NR_SYSCALL_BASE+ 13)
	#define __NR_mknod			(__NR_SYSCALL_BASE+ 14)
	#define __NR_chmod			(__NR_SYSCALL_BASE+ 15)
	#define __NR_lchown			(__NR_SYSCALL_BASE+ 16)
	......
	#define __NR_clock_adjtime		(__NR_SYSCALL_BASE+372)
	#define __NR_syncfs			(__NR_SYSCALL_BASE+373)
	#define __NR_sendmmsg			(__NR_SYSCALL_BASE+374)
	#define __NR_setns			(__NR_SYSCALL_BASE+375)
	#define __NR_process_vm_readv		(__NR_SYSCALL_BASE+376)
	#define __NR_process_vm_writev		(__NR_SYSCALL_BASE+377)

        按格式要求添加新的的系统调用号:

	#define __NR_add			(__NR_SYSCALL_BASE+378)

    3、更新系统调用表

        在 kernel/arch/arm/kernel/calls.S 系统调用表中添加新的一项

        已有的系统调用表:

	/* 0 */	CALL(sys_restart_syscall)
			CALL(sys_exit)
			CALL(sys_fork_wrapper)
			CALL(sys_read)
			CALL(sys_write)
	/* 5 */	CALL(sys_open)
			CALL(sys_close)
			CALL(sys_ni_syscall)		/* was sys_waitpid */
			CALL(sys_creat)
			CALL(sys_link)
			......
	/* 375 */CALL(sys_setns)
			CALL(sys_process_vm_readv)
			CALL(sys_process_vm_writev)
			

        添加新的一项:

			CALL(sys_add)

    4、重新编译内核,内核中就会有新的系统调用

你可能感兴趣的:(深入浅出的Linux系统调用)