Linux下新增和使用系统调用
关键词:__SYSCALL()、SYSCALL_DEFINEx()、syscall()等等。
1. 为什么使用syscall
内核和用户空间数据交换有很多种方式:sysfs、proc、信号等等。
但是syscall效率要高于这些方式,使用起来也更加简单。
缺点是可移植性差,对于新增的系统调用,需要内核和用户空间同步。
2. 如何添加syscall
每个系统调用都有一个系统调用号,这个系统调用号对应sys_call_table[]下标。
通过sys_call_table[syscallid]就可以对应到此系统调用的函数。
在include/uapi/asm/unistd.h中添加__NR_basetime系统调用号,关联系统调用号和系统调用函数。
diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h
index 98e62b9..a1b6503
--- a/arch/csky/include/uapi/asm/unistd.h
+++ b/arch/csky/include/uapi/asm/unistd.h
@@ -, +, @@ __SYSCALL(__NR_ugetrlimit, sys_getrlimit)
#define __NR_sysfs (__NR_arch_specific_syscall + 5)
__SYSCALL(__NR_sysfs, sys_sysfs) +#ifdef CONFIG_PERF_TIMER
+#define __NR_basetime (__NR_arch_specific_syscall + 6)
+__SYSCALL(__NR_basetime, sys_basetime)
+#endif
__SYSCALL()将sys_call_table[]中的系统调用号和系统调用函数关联起来。
#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call), #define sys_fadvise64_64 sys_csky_fadvise64_64
void * const sys_call_table[__NR_syscalls] __page_aligned_data = {
[ ... __NR_syscalls - ] = sys_ni_syscall,
#include <asm/unistd.h>
};
在include/asm/syscalls.h中添加sys_basetime()引用。
#ifdef CONFIG_PERF_TIMER
long sys_basetime(void);
#endif
最后就是sys_basetime()的实现:
SYSCALL_DEFINE0(basetime)
{
return perf_timer_read_us();
}
2.1 SYSCALL_DEFINEx()
当SYSCALL_DEFINEx()的x为0时,很简单就是调用sys_##name()函数。
x为其他值时,同时定义了几个函数,并使用了别名属性。
#define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, ); \
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__))
3. 使用syscall
用户空间系统调用的使用通过syscall函数:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
#include <sys/syscall.h> /* For SYS_xxx definitions */ long syscall(long number, ...);
第一个参数是系统调用号,后面的参数是内核对应sys_##name()函数一致的。
#include <stdio.h>
#include <unistd.h> #define __NR_basetime 250
void main(void)
{
unsigned int timestamp = , i = ; for(i = ; i < ; i++) {
timestamp = syscall(__NR_basetime);
printf("timestamp=%u\n", timestamp);
usleep();
}
}
用户空间通过syscall()函数,触发系统调用,使系统由用户态陷入到内核态。
在系统个调用异常里面获取到系统调用号,以及必须的参数。根据系统调用号和sys_call_table[]找到对应系统调用函数。
以syscall()其余部分参数为入参,执行相关结果。完成后返还给用户空间。
Linux下新增和使用系统调用的更多相关文章
- linux下syscall函数 间接系统调用
NAME syscall - 间接系统调用 SYNOPSIS #define _GNU_SOURCE #include ...
- 在linux下新增一块硬盘的操作。(包含大于2T的硬盘在linux下挂载操作)
转自:http://blog.csdn.net/season_hangzhou/article/details/36423223 一.安装硬盘到物理机上. 二.查看硬盘是否正确安装. 使用“fdisk ...
- Linux 下新增用户的流程
一: 新增用户 1.添加新的用户账号使用useradd命令,其语法如下: 代码:useradd 选项 用户名其中各选项含义如下: 代码:-c comment 指定一段注释性描述.-d 目录 指定用户主 ...
- Linux 下 新增Oracle10g 实例
主要分为5步:创建实例目录,创建密码文件,创建参数文件,创建建库脚本并建库,创建数据字典. 其中,需要特别注意2点: 目录的权限,即用户和所属用户组都要是oracle.可以切换到已存在的oracle用 ...
- Linux 下新增虚拟内存
问题描述,电脑内存1G.在启用elasticsearch的时候,报错 Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memor ...
- Linux 下系统调用的三种方法
系统调用(System Call)是操作系统为在用户态运行的进程与硬件设备(如CPU.磁盘.打印机等)进行交互提供的一组接口.当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系 ...
- Linux C 文件操作,系统调用 -- open()、read() 和 标准I/O库 -- fopen()、fread()
函数汇总: open().write().read().close() fopen().fwrite().fread().fclose() 一.什么是文件 在讲述文件操作之前,我们首先要知道什么是文件 ...
- linux下64位汇编的系统调用(5)
看到这里大家都基本知道了如何进行linux下的汇编系统调用:不过有些童鞋可能会问:那些C库中函数里为我们解决的额外汇编代码你是怎么知道的? 好吧,我承认:我是通过逆向知道的,这貌似有点犯规的嫌疑- 比 ...
- linux下64位汇编的系统调用(3)
背景知识基本交代清楚了,下面我们实际写一个小例子看一下.代码的功能很简单,显示一行文本,然后退出.我们使用了syscall中的write和exit调用,查一下前面的调用号和参数,我们初步总结如下: w ...
随机推荐
- Zuul 详解,带视频
疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长+面试必备之 高并发基础书籍 [Netty Zookeeper Redis 高并发实战 ] 前言 Crazy ...
- 【网络安全】SSH协议科普文
写代码的木公 本文转载自:https://baijiahao.baidu.com/s?id=1612411213158569988&wfr=spider&for=pc 熟悉Linux的 ...
- 关于InterruptedException的两篇博文的转载
博文一:https://www.jianshu.com/p/a8abe097d4ed InterruptedException异常 在了解InterruptedException异常之前应该了解以下的 ...
- 【译】浅谈SOLID原则
SOLID原则是一种编码的标准,为了避免不良设计,所有的软件开发人员都应该清楚这些原则.SOLID原则是由Robert C Martin推广并被广泛引用于面向对象编程中.正确使用这些规范将提升你的代码 ...
- LeetCode 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树
第108题 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10 ...
- Skulpt在线模拟运行Python工具
1. Skulpt是一个完全依靠浏览器端模拟实现Python运行的工具 2. 不需要预处理.插件或服务器端支持,只需编写python并重新载入即可. 3. 由于代码完全是在浏览器中运行的,所以不必担心 ...
- nltk的安装和简单使用
使用python进行自然语言处理,有一些第三方库供大家使用: ·NLTK(Python自然语言工具包)用于诸如标记化.词形还原.词干化.解析.POS标注等任务.该库具有几乎所有NLP任务的工具. ·S ...
- ASP.NET MVC快速开发框架FastExecutor开发全过程感受及总结
困境 追溯到2018年5月份,是个炎热的夏天,毕业后1年7个月我提出了离职,原因是受不了原来公司过度的封装框架感觉一年多毫无进步与实施天天轰炸般的电话,偶然间出去面试了一次发现自己知识真的是比较局限, ...
- Oracle GoldenGate常用参数详解
Oracle GoldenGate常用参数详解http://blog.itpub.net/28389881/viewspace-2564461/
- 用二进制写程序,提升装 X 境界
用二进制来写程序这么反人类的事情,的确是很装的事情,但是它不但是一件很装的事情,也是掌握底层知识的基础能力之一.听我慢慢道来. 程序设计语言有高级语言和低级语言之分,尤其是现在各种编程语言的不断发展, ...