如何在Linux系统中添加新的系统调用
系统调用是应用程序和操作系统内核之间的功能接口。其主要目的是使得用户可以使用操作系统提供的有关设备管理、输入/输入系统、文件系统和进程控制、通信以及存储管理等方面的功能,而不必了解系统程序的内部结构和有关硬件细节,从而起到减轻用户负担和保护系统以及提高资源利用率的作用。
Linux操作系统作为自由软件的代表,它优良的性能使得它的应用日益广泛,不仅得到专业人士的肯定,而且商业化的应用也是如火如荼。在Linux中,大部分的系统调用包含在Linux的libc库中,通过标准的C函数调用方法可以调用这些系统调用。那么,对Linux的发烧友来说,如何在Linux中增加新的系统调用呢?
1 Linux系统调用机制
在Linux系统中,系统调用是作为一种异常类型实现的。它将执行相应的机器代码指令来产生异常信号。产生中断或异常的重要效果是系统自动将用户态切换为核心态来对它进行处理。这就是说,执行系统调用异常指令时,自动地将系统切换为核心态,并安排异常处理程序的执行。Linux用来实现系统调用异常的实际指令是:
QUOTE:
Int $0x80
这一指令使用中断/异常向量号128(即16进制的80)将控制权转移给内核。为达到在使用系统调用时不必用机器指令编程,在标准的C语言库中为每一系统调用提供了一段短的子程序,完成机器代码的编程工作。事实上,机器代码段非常简短。它所要做的工作只是将送给系统调用的参数加载到CPU寄存器中,接着执行int $0x80指令。然后运行系统调用,系统调用的返回值将送入CPU的一个寄存器中,标准的库子程序取得这一返回值,并将它送回用户程序。
为使系统调用的执行成为一项简单的任务,Linux提供了一组预处理宏指令。它们可以用在程序中。这些宏指令取一定的参数,然后扩展为调用指定的系统调用的函数。
这些宏指令具有类似下面的名称格式:
QUOTE:
_syscallN(parameters)
其中N是系统调用所需的参数数目,而parameters则用一组参数代替。这些参数使宏指令完成适合于特定的系统调用的扩展。例如,为了建立调用setuid()系统调用的函数,应该使用:
QUOTE:
_syscall1( int, setuid, uid_t, uid )
syscallN( )宏指令的第1个参数int说明产生的函数的返回值的类型是整型,第2个参数setuid说明产生的函数的名称。后面是系统调用所需要的每个参数。这一宏指令后面还有两个参数uid_t和uid分别用来指定参数的类型和名称。
另外,用作系统调用的参数的数据类型有一个限制,它们的容量不能超过四个字节。这是因为执行int $0x80指令进行系统调用时,所有的参数值都存在32位的CPU寄存器中。使用CPU寄存器传递参数带来的另一个限制是可以传送给系统调用的参数的数目。这个限制是最多可以传递5个参数。所以Linux一共定义了6个不同的_syscallN()宏指令,从_syscall0()、_syscall1()直到_syscall5()。
一旦_syscallN()宏指令用特定系统调用的相应参数进行了扩展,得到的结果是一个与系统调用同名的函数,它可以在用户程序中执行这一系统调用。
2 添加新的系统调用
如果用户在Linux中添加新的系统调用,应该遵循几个步骤才能添加成功,下面几个步骤详细说明了添加系统调用的相关内容。
(1) 添加源代码
第一个任务是编写加到内核中的源程序,即将要加到一个内核文件中去的一个函数,该函数的名称应该是新的系统调用名称前面加上sys_标志。假设新加的系统调用为mycall(int number),在/usr/src/linux/kernel/sys.c文件中添加源代码,如下所示:
QUOTE:
asmlinkage int sys_mycall(int number)
{
return number;
}
作为一个最简单的例子,我们新加的系统调用仅仅返回一个整型值。
(2) 连接新的系统调用
添加新的系统调用后,下一个任务是使Linux内核的其余部分知道该程序的存在。为了从已有的内核程序中增加到新的函数的连接,需要编辑两个文件。
在我们所用的Linux内核版本(RedHat 6.0,内核为2.2.5-15)中,第一个要修改的文件是:
QUOTE:
/usr/src/linux/include/asm-i386/unistd.h
该文件中包含了系统调用清单,用来给每个系统调用分配一个唯一的号码。文件中每一行的格式如下:
QUOTE:
#define __NR_name NNN
其中,name用系统调用名称代替,而NNN则是该系统调用对应的号码。应该将新的系统调用名称加到清单的最后,并给它分配号码序列中下一个可用的系统调用号。我们的系统调用如下:
QUOTE:
#define __NR_mycall 191
系统调用号为191,之所以系统调用号是191,是因为Linux-2.2内核自身的系统调用号码已经用到190。
第二个要修改的文件是:
QUOTE:
/usr/src/linux/arch/i386/kernel/entry.S
该文件中
- 嵌入式linux应用开发之:初识Qt(03-04)
- 检测Linux系统是否被黑的技巧(05-05)
- Linux系统计算机死机的故障原因(05-08)
- Linux系统下MTD/CFI驱动介绍(05-23)
- 修改Linux系统下22端口的两种方法(07-08)
- 无需安装即可运行或演示Linux系统的方法(06-06)
- 婵°倕鍊瑰玻鎸庮殽閸モ晙鐒婇柛鏇ㄥ灱閺嗐儳鈧鎮堕崕鎶藉煝閼测晜鏆滈柛顐g箓閹鏌熺€涙ê濮囬柣鎾规硶閹峰顢橀悢鍛婄暚缂備礁顑呴鍛淬€冨⿰鍛晳闁跨噦鎷�
闂佺ǹ绻堥崝宥夊蓟閻斿憡濯寸€广儱鎷嬮崝鍛槈閺冨倸孝闁汇劎濮甸敍鎰板箣濠婂懐鎳囨繛鎴炴尰濮樸劑鎮¢敍鍕珰闁糕槅鍘剧粈澶愭煙缂佹ê濮囩€规洖鐭傞幆宥夊棘閸喚宀涢悗瑙勬偠閸庢壆绱為弮鍫熷殑闁芥ê顦~鏃堟煥濞戞ǹ瀚板┑顕呬邯楠炲啴濡搁妷锕€娓愰梻渚囧亞閸犳劙宕瑰鑸碘拹濠㈣埖鐡曠粈瀣归崗鍧氱細妞ゎ偄鎳橀幆鍐礋椤愩倖顔忔俊顐ゅ閸ㄥ灚瀵奸幇顔剧煓閻庯綆浜為悷锟�...
- 婵炴垶鎼╅崢鐐殽閸モ晙鐒婇柛鏇ㄥ灱閺嗐儳鈧鎮堕崕鎶藉煝閼测晜鏆滈柛顐g箓閹鏌熺€涙ê濮囬柣鎾规硶閹峰顢橀悢鍛婄暚缂備礁顑呴鍛淬€冨⿰鍛晳闁跨噦鎷�
缂備緡鍣g粻鏍焵椤掑﹥瀚�30婵犮垼鍩栧畝绋课涢鍌欑剨闁告洦鍨奸弳銉╂煕閳哄喚鏀版い鏂垮閹风娀宕滆閺屻倝鏌ㄥ☉妯侯殭缂佹鎸鹃埀顒傤攰閸╂牕顔忕捄銊﹀珰闁规儳鎳愮粈澶愭煕閺傜儤娅呮い鎺斿枛瀹曘劌螣閻戞ê娓愰梻渚囧亞閸犳洟骞撻鍫濈濡鑳堕鍗炩槈閹垮啩绨婚柟顔奸叄瀵粙鎮℃惔锝嗩啅婵☆偆澧楅崹鍨閹邦喚鐭欓悗锝庝簽閻熷酣鏌i妸銉ヮ伂妞も晪绠戞晥闁跨噦鎷�...
- Agilent ADS 闂佽桨鐒﹂悷銉╊敆閻旂厧鏄ョ痪顓炴媼閸炴煡鎮归崶褍鈷旈柍璇插悑缁鸿棄螖閸曞灚顥�
婵炴垶鎸婚幐鎼侇敊瀹ュ绠抽柛顐秵閸わ箓鏌ㄥ☉妯垮闁告瑥绻樺Λ鍐閿濆骸鏁奸柣鐔哥懐閺嬪儊S闂佸憡鑹剧€氼噣锝為幒妤€绀夐柣鏃囶嚙閸樻挳鏌涘⿰鍐濞村吋鍔楃划娆戔偓锝庝簽鐎瑰鏌i姀鈺冨帨缂侀亶浜跺畷婵嬪煛閸屾矮鎲鹃梺鐑╁亾閸斿秴銆掗崼鏇熷剹妞ゆ挾濮甸悾閬嶆煛閸愩劎鍩f俊顐ユ硶閳ь剚鍐荤紓姘辨閻у挷S...
- HFSS闁诲孩鍐荤紓姘卞姬閸曨垰鏄ョ痪顓炴媼閸炴煡鎮归崶褍鈷旈柍璇插悑缁鸿棄螖閸曞灚顥�
闁荤姍鍐仾缂佽鐒︾粙澶愬箻閹颁礁鏅欓梺鐟版惈閻楁劙顢氶幎鑺ユ櫖閻忕偠妫勫鍧楁⒒閸稑鐏辨い鏂款樀楠炴帡宕峰▎绂⊿闂佹眹鍔岀€氼剚鎱ㄥ☉銏″殑闁芥ê顦扮€氭煡骞栫€涙ɑ鈷掗柡浣靛€濋弫宥囦沪閽樺鐩庨梺鍛婃煛閺呮粓宕戝澶婄闁靛ň鏅滃銊х磼椤栨繂鍚圭紒顔芥そ瀹曠兘寮跺▎鎯уΤ婵炴垶姊绘慨鐢垫暜婢舵劕绠垫い鈥抽敪SS...
- CST閻庣敻鍋婇崰妤冧焊濠靛棭鍟呴柕澶堝€楃粙濠囨倵楠炲灝鈧洟鎮$捄銊﹀妞ゆ挾鍠愬▓宀€绱掔€n亶鍎忔い銊︾矌閹叉鏁撻敓锟�
闂佸搫顦€涒晛危閹存緷铏光偓锝傛櫅閻︽粓鎮规担绛嬪殝缂佽鲸绻堝畷妤呭Ω閳哄倹銆冮柣鐘辩瀵泛顔忕欢缍璗闂佸憡鑹剧€氫即濡村澶婄闁绘棁顕ч崢鎾煕濠婂啳瀚板ù鍏煎姉缁瑧鈧綆浜炵€瑰鏌i姀鈺冨帨缂佽鲸绻堝畷婵嬪煛閸屾矮鎲鹃棅顐㈡祩閸嬪﹪鍩€椤掑倸鏋欓柛銈嗙矌閳ь剚鍐婚梽鍕暜婢舵劕绠垫い鈥愁敍T闁荤姳鐒﹀畷姗€顢橀崨濠冨劅闁哄啫鍊归弳锟�...
- 闁诲繐绻愮€氫即銆傞崼鏇炴槬闁惧繗顕栭弨銊╂煕閳哄喚鏀版い鏂垮閹风娀宕滆閺岋拷
婵炴垶鎸稿ú锝囩箔閳ь剙螖閸屾惮鎴﹀Χ婵傚摜宓侀柛鎰级閸曢箖鎮硅閸ゆ牜妲愬┑鍥ㄤ氦婵炲棗娴烽弰鍌炴偣閸パ冣挃闁宠鍚嬬粙澶嬫姜閹殿喚鈽夐梺闈╄礋閸斿矂鎯冮悩绛圭矗闁瑰鍋涜灇闂佸搫鐗滈崹鍫曘€傞锕€鏄ラ柣鏃€鐏氭禍锝夋倶閻愬瓨绀冮悗姘辨暬閹虫ê顫濋崜褏顦梺鐟扮仛閹搁绮崨鏉戦敜婵﹩鍓涢弶浠嬫煟閵娿儱顏х紒妤佹尰缁嬪顫濋鍌氭暏缂佺虎鍘搁崑锟�...
- 閻庣敻鍋婇崰妤冧焊濠靛牅鐒婇柛鏇ㄥ灱閺嗐儲绻涢弶鎴剶闁革絾妞介獮娆忣吋閸曨厾鈻曢梺绯曟櫇椤㈠﹪顢欓崟顓熷珰闁告挆鈧弻銈夋煕濮橆剛澧︽繛澶涙嫹
闁荤姵鍔﹂崢娲箯闁秴瑙﹂柛顐犲劜閼茬娀鏌¢崶銊︾稇闁汇倕瀚伴獮鍡涙偑閸涱垳顦紓鍌氬暞閸ㄧ敻宕规惔銊ノュ〒姘e亾妞わ絽澧庨幏顐﹀矗濡搫纾块梺闈涙閼冲爼濡靛顑芥灃闁靛繒濮甸悵銈夋煏閸℃洘顦峰ǎ鍥э躬瀹曪綁鏌ㄧ€n剛鍩嶉梺鎸庣☉閺堫剟宕瑰⿰鍛暫濞达絽婀辨竟澶愭煛瀹ュ妫戠紒銊ユ健閺屽懘鏁撻敓锟�...