从零开始之驱动发开、linux驱动(十五、对系统调用函数的封装)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_16777851/article/details/82714326

在分析系统调用函数之前,先分析几个重要的宏。

在2.6后期的内核中增加的,用宏来封装了一些通用性的东西,使正的系统调用实现函数看起来简洁了很多,这里我们进行简单的展开分析。

#define __stringify_1(x...)	#x
#define __stringify(x...)	__stringify_1(x)

#define __MAP0(m,...)
#define __MAP1(m,t,a) m(t,a)
#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
#define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
#define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
#define __MAP(n,...) __MAP##n(__VA_ARGS__)

#define __SC_DECL(t, a)	t a

#ifndef asmlinkage_protect
# define asmlinkage_protect(n, ret, args...)	do { } while (0)
#endif


#define SYSCALL_METADATA(sname, nb, ...)



#define SYSCALL_DEFINE0(sname)					\
	SYSCALL_METADATA(_##sname, 0);				\
	asmlinkage long sys_##sname(void)

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)

#define SYSCALL_DEFINEx(x, sname, ...)				\
	SYSCALL_METADATA(sname, x, __VA_ARGS__)			\
	__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
#define __SYSCALL_DEFINEx(x, name, ...)					\
	asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))	\
		__attribute__((alias(__stringify(SyS##name))));		\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
	{								\
		long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));	\
		__MAP(x,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))

其中,我们真正被系统使用的是下面的几个,分为7个等级,越小越核心。

其中SYSCALL_DEFINE0和SYSCALL_DEFINE1...他们的实现不一致,我们对0单独分析。

#define SYSCALL_DEFINE0(sname)					\
	SYSCALL_METADATA(_##sname, 0);				\
	asmlinkage long sys_##sname(void)

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)

1. SYSCALL_DEFINE0

#define SYSCALL_DEFINE0(sname)					\
	SYSCALL_METADATA(_##sname, 0);				\
	asmlinkage long sys_##sname(void)

搜索,可以发现SYSCALL_METADATA在本文件中定义了两个

#ifdef CONFIG_FTRACE_SYSCALLS        /* 我们没定义 */
    ......
#define SYSCALL_METADATA(sname, nb, ...)			\
	.static const char *types_##sname[] = {			\
		__MAP(nb,__SC_STR_TDECL,__VA_ARGS__)		\
	};							\
	static const char *args_##sname[] = {			\
		__MAP(nb,__SC_STR_ADECL,__VA_ARGS__)		\
	};							\
	SYSCALL_TRACE_ENTER_EVENT(sname);			\
	SYSCALL_TRACE_EXIT_EVENT(sname);			\
	static struct syscall_metadata __used			\
	  __syscall_meta_##sname = {				\
		.name 		= "sys"#sname,			\
		.syscall_nr	= -1,	/* Filled in at boot */	\
		.nb_args 	= nb,				\
		.types		= nb ? types_##sname : NULL,	\
		.args		= nb ? args_##sname : NULL,	\
		.enter_event	= &event_enter_##sname,		\
		.exit_event	= &event_exit_##sname,		\
		.enter_fields	= LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
	};							\
	static struct syscall_metadata __used			\
	  __attribute__((section("__syscalls_metadata")))	\
	 *__p_syscall_meta_##sname = &__syscall_meta_##sname;
#else



#define SYSCALL_METADATA(sname, nb, ...)        /* 我们使用这个,默认为空 */
#endif

搜索.config我们并没有定义CONFIG_FTRACE_SYSCALLS宏,所以这个宏是空的

即SYSCALL_DEFINE0(name)应该是这样的

#define SYSCALL_DEFINE0(sname)		asmlinkage long sys_##sname(void)

其中asmlinkage是gcc的c语言预定义的关键字,

在标准C系中函数的形参在实际传入参数的时候会涉及到参数存放的问题,那么这些参数存放在哪里呢?

对x86比较了解的话,应该知道这些函数参数和函数内部局部变量一起被分配到了函数的局部堆栈中。linux操作系统支持多种CPU架构,比如x86、ppc和arm等,在不同的处理器结构上不能保证都是通过 局部栈传递参数的。ARM对函数调用过程中的传参定义了一套规则,即 ATPCS,规则中明确指出ARM中R0-R4都是作为通用寄存器使用,在函数调用时处理器从R0-R4中获取参数,在函数返回时再 将需要返回的参数一次存到R0-R4中,也就是说可以将函数参数直接存放在寄存器中,所以为了严格区别函数参数的存放位置,引入了两个标记,即 asmlinkage和FASTCALL,前者表示将函数参数存放在局部栈中,后者则是通知编译器将函数参数用寄存器保存起来。

在x86平台使用,gcc的c语言扩展关键字,__attribute__

/* 告诉gcc编译器该函数不需要通过任何寄存器来传递参数,参数只是通过堆栈来传递。 */
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))    
/* 告诉gcc编译器这个函数可以通过寄存器传递多达3个的参数,这3个寄存器依次为EAX、EDX 和 ECX。更多的参数才通过堆栈传递。这样可以减少一些入栈出栈操作,因此调用比较快。 */
#define FASTCALL(x) x __attribute__((regparm(3)))
#define fastcall __attribute__((regparm(3)))

在arm平台时,因为arm的传参综寻ATPCS规则,所以为空

#ifndef FASTCALL
#define FASTCALL(x) x
#define fastcall    /* 空 */
#endif


#ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE        /* 对arm为空格,没实际意义 */
#endif

#ifndef asmlinkage
#define asmlinkage CPP_ASMLINKAGE
#endif

可见对SYSCALL_DEFINE0直接就转换为如下

#define SYSCALL_DEFINE0(sname)					\
	SYSCALL_METADATA(_##sname, 0);				\
	asmlinkage long sys_##sname(void)

long sys_sname(void)

以fork函数为例

SYSCALL_DEFINE0(fork)
{

	return do_fork(SIGCHLD, 0, 0, NULL, NULL);

	/* can not support in nommu mode */
	return -EINVAL;

}


其实就是直接替换而已
long sys_fork(void)
{

	return do_fork(SIGCHLD, 0, 0, NULL, NULL);

	/* can not support in nommu mode */
	return -EINVAL;

}

2.SYSCALL_DEFINE1

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)    /* 3个参数 */
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)    /* 5个参数 */
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)    /* 7个参数 */
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)    /* 9个参数 */
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)    /* 11个参数 */
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)    /* 13个参数 */
/* 采用递归方式替换,每次都是增加2个(一个是参数类型,一个是参数名) */

SYSCALL_DEFINE宏的作用是用来解析不同参数个数的函数时使用的,因为其它的都是类似的,这里我就用比较简单的1为例进行分析。

第一步


#define SYSCALL_DEFINEx(x, sname, ...)				\
	SYSCALL_METADATA(sname, x, __VA_ARGS__)			\       /* 这句我们默认删除 */
	__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)


#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)

替换后
#define SYSCALL_DEFINE1(name, ...)

    __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)        /* 1和name前的_ */

第二步(先替换掉直接可见的部分)

__SYSCALL_DEFINEx(1, _sname, __VA_ARGS__) 


#define __SYSCALL_DEFINEx(x, name, ...)					\
	asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))	\
		__attribute__((alias(__stringify(SyS##name))));		\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
	{								\
		long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));	\
		__MAP(x,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))


#define __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)					\
	asmlinkage long sys_name(__MAP(1,__SC_DECL,__VA_ARGS__))	\
		__attribute__((alias(__stringify(SyS_name))));		\
	static inline long SYSC_name(__MAP(1,__SC_DECL,__VA_ARGS__));	\/* 声明一个SYS_name位名字的函数 */
	asmlinkage long SyS_name(__MAP(1,__SC_LONG,__VA_ARGS__));	\    /* 声明Sys_name为名字的函数 */
	asmlinkage long SyS_name(__MAP(1,__SC_LONG,__VA_ARGS__))	\    /* 定义Sys_name为名字的一个函数 */
	{								\
		long ret = SYSC_name(__MAP(1,__SC_CAST,__VA_ARGS__));	\
		__MAP(1,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(1, ret,__MAP(1,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC_name(__MAP(1,__SC_DECL,__VA_ARGS__))    /* 定义一个SYS_name为名的函数头(这里没函数体) */

去掉asmlinkage 
#define __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)			\
	long sys_name(__MAP(1,__SC_DECL,__VA_ARGS__))	                \
		__attribute__((alias(__stringify(SyS_name))));		\
	static inline long SYSC_name(__MAP(1,__SC_DECL,__VA_ARGS__));	\    /* 声明一个SYS_name位名字的函数 */
	long SyS_name(__MAP(1,__SC_LONG,__VA_ARGS__));	                \    /* 声明Sys_name为名字的函数 */
	long SyS_name(__MAP(1,__SC_LONG,__VA_ARGS__))	                \    /* 定义Sys_name为名字的一个函数 */
	{								\
		long ret = SYSC_name(__MAP(1,__SC_CAST,__VA_ARGS__));	\
		__MAP(1,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(1, ret,__MAP(1,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC_name(__MAP(1,__SC_DECL,__VA_ARGS__))    /* 定义一个SYS_name为名的函数头(这里没函数体) */

第三步(继续优化替换第二步)

/* x变成字符串形式 */
#define __stringify_1(x...)	#x        
#define __stringify(x...)	__stringify_1(x)    

#define __MAP0(m,...)
#define __MAP1(m,t,a) m(t,a)
#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
#define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
#define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
#define __MAP(n,...) __MAP##n(__VA_ARGS__)

#define __SC_DECL(t, a)	t a    /* 替换参数类型,带变量名 */
#define __TYPE_IS_L(t)	(__same_type((t)0, 0L))
#define __TYPE_IS_UL(t)	(__same_type((t)0, 0UL))
#define __TYPE_IS_LL(t) (__same_type((t)0, 0LL) || __same_type((t)0, 0ULL))
#define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a
#define __SC_CAST(t, a)	(t) a
#define __SC_ARGS(t, a)	a        /* 替换参数类型,不带变量名 */
#define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long))


#ifndef asmlinkage_protect
# define asmlinkage_protect(n, ret, args...)	do { } while (0)
#endif

去掉asmlinkage 
#define __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)			\
	long sys_name(__MAP(1,__SC_DECL,__VA_ARGS__))	                \
		__attribute__((alias(__stringify(SyS_name))));		\
	static inline long SYSC_name(__MAP(1,__SC_DECL,__VA_ARGS__));	\    /* 声明一个SYS_name位名字的函数 */
	long SyS_name(__MAP(1,__SC_LONG,__VA_ARGS__));	                \    /* 声明Sys_name为名字的函数 */
	long SyS_name(__MAP(1,__SC_LONG,__VA_ARGS__))	                \    /* 定义Sys_name为名字的一个函数 */
	{								\
		long ret = SYSC_name(__MAP(1,__SC_CAST,__VA_ARGS__));	\
		__MAP(1,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(1, ret,__MAP(1,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC_name(__MAP(1,__SC_DECL,__VA_ARGS__))    /* 定义一个SYS_name为名的函数头(这里没函数体) */


继续替换
先替换掉__stringify,即把参数字变成字符串
#define __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)			\
	long sys_name(__MAP(2,__SC_DECL,__VA_ARGS__))	                \
		__attribute__((alias("SyS_name"))));		\
	static inline long SYSC_name(__MAP(2,__SC_DECL,__VA_ARGS__));	\    /* 声明一个SYS_name位名字的函数 */
	long SyS_name(__MAP(2,__SC_LONG,__VA_ARGS__));	                \    /* 声明Sys_name为名字的函数 */
	long SyS_name(__MAP(2,__SC_LONG,__VA_ARGS__))	                \    /* 定义Sys_name为名字的一个函数 */
	{								\
		long ret = SYSC_name(__MAP(2,__SC_CAST,__VA_ARGS__));	\
		__MAP(2,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(1, ret,__MAP(2,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC_name(__MAP(2,__SC_DECL,__VA_ARGS__))    /* 定义一个SYS_name为名的函数头(这里没函数体) */


这一步替换掉__MAP(xxx,xxx,xxx;
根据上面宏规则

替换掉后可已得到相应的参数列表,我们这里1代表是有3个参数(除去name,只有两个了)


#define __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)			\
	long sys_name(参数类型 参数名)	                                \
		__attribute__((alias("SyS_name")));		\
	static inline long SYSC_name(参数类型 参数名);	                \    /* 声明一个SYS_name位名字的函数 */
	long SyS_name(参数类型 参数名);	                            \    /* 声明Sys_name为名字的函数 */
	long SyS_name(参数类型 参数名)	                                \    /* 定义Sys_name为名字的一个函数 */
	{								\
		long ret = SYSC_name( 参数名);	                \
		__MAP(2,__SC_TEST,__VA_ARGS__);				        \
		__PROTECT(1, ret,参数名);	                \
		return ret;						\
	}								\
	static inline long SYSC_name(参数类型 参数名)    /* 定义一个SYS_name为名的函数头(这里没函数体) */


#ifndef asmlinkage_protect
# define asmlinkage_protect(n, ret, args...)	do { } while (0)
#endif

#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)    /* 为空删掉 */
下面这个是编译时调试用的也删除掉
#define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long))



#define __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)			\
	long sys_name(参数类型 参数名)	                                \
		__attribute__((alias("SyS_name")));		\
	static inline long SYSC_name(参数类型 参数名);	                \    /* 声明一个SYS_name位名字的函数 */
	long SyS_name(参数类型 参数名);	                            \    /* 声明Sys_name为名字的函数 */
	long SyS_name(参数类型 参数名)	                                \    /* 定义Sys_name为名字的一个函数 */
	{								\
		long ret = SYSC_name(参数名);
	}								\
	static inline long SYSC_name(参数类型 参数名)    /* 定义一个SYS_name为名的函数头(这里没函数体) */
#define __SYSCALL_DEFINEx(1, _sname, __VA_ARGS__)			\
	long sys_name(参数类型 参数名)	                                \
		__attribute__((alias("SyS_name")));		\
	static inline long SYSC_name(参数类型 参数名);	                \    /* 声明一个SYS_name位名字的函数 */
	long SyS_name(参数类型 参数名);	                            \    /* 声明Sys_name为名字的函数 */
	long SyS_name(参数类型 参数名)	                                \    /* 定义Sys_name为名字的一个函数 */
	{								\
		long ret = SYSC_name(参数名);	                \
		return ret;						\
	}								\
	static inline long SYSC_name(参数类型 参数名)    /* 定义一个SYS_name为名的函数头(这里没函数体) */


上面宏中的下面这句的作用是对 SyS_name这个函数名,起一个别名叫sys_name,
long sys_name(参数类型 参数名)	 __attribute__((alias("SyS_name")));		

上面虽然没具体参数,但通过结构我们可以看到,起始就是定义了一下东西


long sys_name(参数1,参数2,参数3)	 __attribute__((alias("SyS_name")));    /* 给SyS_name起别名 */
	
static inline long SYSC_name(参数类型 参数名);    /* 声明SYSC_name函数,因为SyS_name里面要用,而SYSC_name又在SyS_name下面定义,所以要声明 */	
               
long SyS_name(参数类型 参数名);	 /* 定义并声明SyS_name函数 */	                           
long SyS_name(参数类型 参数名)	                              
{								\
	long ret = SYSC_name(参数名);	          
	return ret;						
}								
static inline long SYSC_name(参数类型 参数名)   

第四步,带入一个SYSCALL_DEFINE1定义的查看最终版本

SYSCALL_DEFINE1(close, unsigned int, fd)
{
	int retval = __close_fd(current->files, fd);

	/* can't restart close syscall because file table entry was cleared */
	if (unlikely(retval == -ERESTARTSYS ||
		     retval == -ERESTARTNOINTR ||
		     retval == -ERESTARTNOHAND ||
		     retval == -ERESTART_RESTARTBLOCK))
		retval = -EINTR;

	return retval;
}

long sys_name(参数类型 参数名)	 __attribute__((alias("SyS_name")));    /* 给SyS_name起别名 */
	
static inline long SYSC_name(参数类型 参数名);    /* 声明SYSC_name函数,因为SyS_name里面要用,而SYSC_name又在SyS_name下面定义,所以要声明 */	
               
long SyS_name(参数类型 参数名);	 /* 定义并声明SyS_name函数 */	                           
long SyS_name(参数类型 参数名)	                              
{								\
	long ret = SYSC_name( 参数名);	          
	return ret;						
}								
static inline long SYSC_name(参数类型 参数名)   



替换后
long sys_close(unsigned int fd)	 __attribute__((alias("SyS_close")));    /* 给SyS_name起别名 */
	
static inline long SYSC_close(unsigned int fd);    /* 声明SYSC_close函数,因为SyS_close里面要用,而SYSC_name又在SyS_close下面定义,所以要声明 */	
               
long SyS_close(unsigned int fd);	 /* 定义并声明SyS_name函数 */	                           
long SyS_close(unsigned int fd)	                              
{								\
	long ret = SYSCclose(fd);	          
	return ret;						
}								
static inline long SYSC_close(unsigned int fd)   
{
	int retval = __close_fd(current->files, fd);

	/* can't restart close syscall because file table entry was cleared */
	if (unlikely(retval == -ERESTARTSYS ||
		     retval == -ERESTARTNOINTR ||
		     retval == -ERESTARTNOHAND ||
		     retval == -ERESTART_RESTARTBLOCK))
		retval = -EINTR;

	return retval;
}


可见系统调用中的sys_close是通过原来的SyS_close函数其别名来实现的
同时通过类似的SYSCALL_DEFINEX宏实现了SyS_close函数,

所有的系统调用都是使用类似的方式实现(起别名)
那为什么要实现两个函数呢,不直接用SYSC_close起别名呢


在Sys_close里面本来还有

系统调用调试相关的代码
__MAP(x,__SC_TEST,__VA_ARGS__);   
__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	


/* 再看一遍原来的宏 */
#define __SYSCALL_DEFINEx(x, name, ...)					\
	asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))	\
		__attribute__((alias(__stringify(SyS##name))));		\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));	\
	asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
	{								\
		long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));	\
		__MAP(x,__SC_TEST,__VA_ARGS__);				\
		__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\
		return ret;						\
	}								\
	static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))




因为上面的调试相关的代码对每个系统调用都是通用的,使用宏可以看起来减少重复的代码量
所以有封装了一个函数,当然使用了函数调用又为了不影响系统开销SYSC_xxxx又都使用linine被内联到SyS_xxxx里面了

long sys_close(unsigned int fd)	 __attribute__((alias("SyS_close")));    /* 给SyS_name起别名 */
	
static inline long SYSC_close(unsigned int fd);    /* 声明SYSC_close函数,因为SyS_close里面要用,而SYSC_name又在SyS_close下面定义,所以要声明 */	
               
long SyS_close(unsigned int fd);	 /* 定义并声明SyS_name函数 */	                           
long SyS_close(unsigned int fd)	                              
{								\
	long ret = SYSCclose(fd);	
    __MAP(x,__SC_TEST,__VA_ARGS__);				\        /* 调试相关 */
	__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\          
	return ret;						
}								
static inline long SYSC_close(unsigned int fd)   
{
	int retval = __close_fd(current->files, fd);

	/* can't restart close syscall because file table entry was cleared */
	if (unlikely(retval == -ERESTARTSYS ||
		     retval == -ERESTARTNOINTR ||
		     retval == -ERESTARTNOHAND ||
		     retval == -ERESTART_RESTARTBLOCK))
		retval = -EINTR;

	return retval;
}

下面放出几个其他的系统调用,大家参考上面的解析,应该一下就知道了怎么转换了

SYSCALL_DEFINE0

SYSCALL_DEFINE0(getpid)
{
	return task_tgid_vnr(current);
}


void sys_getpid(void)
{
    return task_tgid_vnr(current);
}

SYSCALL_DEFINE1

SYSCALL_DEFINE1(exit, int, error_code)
{
	do_exit((error_code&0xff)<<8);
}


long sys_exit(int error_code)	 __attribute__((alias("SyS_exit")));  	
static inline long SYSC_exit(int error_code);            
long SyS_exit(int error_code);
	                        
long SyS_exit(int error_code)	                              
{								\
	long ret = SYSC_exit( error_code);	          
	return ret;						
}								
static inline long SYSC_exit(int error_code)   
{
    do_exit((error_code&0xff)<<8);
}

SYSCALL_DEFINE2

SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
{
	return sys_fchmodat(AT_FDCWD, filename, mode);
}


long sys_chmod(const char __user *filename, umode_t mode)	 __attribute__((alias("SyS_chmod")));  	
static inline long SYSC_chmod(const char __user *filename, umode_t mode);            
long SyS_chmod(const char __user *filename, umode_t mode);
	                        
long SyS_chmod(const char __user *filename, umode_t mode)	                              
{								\
	long ret = SYSC_chmod(filename, modee);	          
	return ret;						
}								
static inline long SYSC_chmod(const char __user *filename, umode_t mode)   
{
    return sys_fchmodat(AT_FDCWD, filename, mode);
}

......

其它自行脑补

猜你喜欢

转载自blog.csdn.net/qq_16777851/article/details/82714326