LINUX系统调用及exit实例分析

LINUX系统调用及exit实例分析
LINUX系统调用及exit实例分析

LINUX系统调用及exit实例分析

计算机系962班黄山松9615158

序言: <计算机操作系统>课程即将结束, 经过这一学期的学习,我对操作系统, 尤其是Linux系统有了初步认识,虽然限于英语水平, 对外籍参考书较少涉及, 但也深有收获. 特别是分析系统调用的源码, 揭开了系统核心的神密的面纱.

Linux系统的结构

在清华大学出版的<操作系统基础> (屠立德.屠祁编著)曾经见过这样一幅Unix 结构图,我觉得对Linux 同样适用,经少量改动,示意如下:

例图Linux 系统的结构

Linux 系统由内核和用户层组成. 内核是Linux 系统的心脏. 由汇编文件和C 语言文件构成. 汇编文件主要用于系统初启. 中断处理等与硬件细节密切相关的部分, 此处本文不作详解. 内核按以下功能分块:

1.存贮管理

2.进程管理

3.进程通信

4.中断.陷阱与系统调用( 此处陷阱仅狭义为异常)

5.输入输出管理

6.文件系统

由例图及上面的分类, 我们至少知道了为什么要有系统调用. 用最简单的话来说, 系统调用就是硬件与软件的接口. 或者说内核与外壳的接口.

实际上, Linux 的系统核心的所有程序都是作为进程的一部分而运行的,被包括在每一个进程的虚拟地址空间里, so 每一个进程都包含着两个部分: 系统程序部分和用户程序部分. 一进程在用户态运行时, 执行的是用户程序;若中断而转入核心态, 执行系统核心程序.

下面就让我们进入

一.系统调用的流程

●大致流程如下:

start_kernel ( ) 函数( i386/main.c )

trap_init ( ) 函数( kernel/trap.c )

宏set_grap_gate ( ) 函数( asm/system.h )

●start_kernel ( ) 提供了各种trap 入口. 通过调用trap_init ( ) 函数设置,

而trap_init ( ) 又通过调用set_ system_gate( 0x80,&system_call ) 实现具

体操作.

●在Linux 系统调用中, 首先由0x80 号中断进入系统调用入口,通过系统调

用表保存系统调用服务函数的入口地址来实现,那好就从中断开始吧. 1.1关于中断

在386体系结构中,承认两类事件。

1.异常(exceptions)

2.中断(interrupts)

他们都会引起“上下文转换”,(context switch) 同时建立一个过程(procedure)或任务(task)

中断可以随时随地发生(包括在执行程序时)所以用来响应硬件信号。

而异常则由指令内部错误引起。

在80386中,又把中断分为两种:

●可屏蔽中断(Miscible Interrupt)如IO 中断等

●不可屏蔽中断(NonMaskable Interrupt)如机器内部故障. 掉电中断等

异常也分为两种:

●处理器异常如overflow 等

●编程(调试)异常如trap 指令或INT 中断指令等

0x80 号中断的设置

●在Linux中,系统调用的执行是通过中断或异常的方式来进行的,他将

执行相应的机器代码指令,来产生中断或异常信号,产生中断或异常的重要效果是系统自动将用户模式切换为核心模式,并安排异常处理程序的执行。

●Linux设置了一个可屏蔽中断int 0x80,0x80就是系统调用的一个矢量地

址。这个中断矢量表是在系统启动时就初始化好的,以及一些矢量地址,

如系统时钟。通过矢量0x80把控制传给kernel

在宏set_system_gate ( ) (“include/asm-i386/system.h )

#define set_system_gate(n,addr) \

_set_gate(&idt[n],15,3,addr)

同一文件中

#define _set_gate(gate_addr,type,dpl,addr) \

__asm__ __volatile__ (“movw %%dx,%%ax\n\t” \

“movw %2,%%dx\n\t” \

“movl %%eax,%0\n\t” \

“movl %%edx,%1” \

:”=m” (*((long *) (gate_addr))), \

“=m” (*(1+(long *) (gate_addr))) \

:”i” ((short) (0x8000+(dpl<<13)+(type<<8))), \

“d” ((char *) (addr)),”a” (KERNEL_CS << 16) \

:”ax”,”dx”

调用该宏,将使addr地址值置入gate_addr中的地址值所指向的内存单元中,而_set_gate(&idt[n],15,3,addr) 使中断向量描述表中的第128项

(即16进制第80项)保存了0x80号中断的中断服务程序,即system_call。

1.2系统调用的入口

在头文件“include/asm-i386/unistd.h”中,定义了163个系统调用有关的宏,包括系统调用序号,如:

#define __NR_setup 0

#define __NR_exit 1

#define __NR_fork 2

* * * * *

同时定义了一系列形似_syscallX(type,name, type1,arg1,type2,arg2……)的宏.(type , type1等用做系统调用的参数类型有一个限制,它们的容量不能超过4个字节, 因为在执行int 0x80 时,所有参数都是通过寄存器传递的,在386体系结构中,寄存器是32位的,所以,他们的容量不能超过4个字节(32位); 使用CPU寄存器做参数传递还有一个限制, 即可以传递的参数的数目最大不超过五个参数,Linux 一共定义了六个不同的宏syscallX ( ): syscall0 ( ) 到syscall5 ( ). )

下面以X=3即叁个参数为例,解释该宏:

#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \

type name(type1 arg1,type2 arg2,type3 arg3) \

{ \

long __res; \

__asm__ volatile ("int $0x80" :"=a" (__res) : "0"\

(__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \

"d" ((long)(arg3))); \

if (__res>=0)

return (type) __res; errno=-__res; \

return -1; \

}

该宏的第一个参数是一类类型参数,它指明系统调用返回值的类型,第二个参数指明系统调用的名称。若还有别的参数, 则第2i个参数是系统调用函数的第i个参数的类型,第2i+1个参数是系统调用函数的第i个参数, 该宏的主体部分是一内联汇编,它通过汇编代码段__asm__volotile调用中断"int $0x80"将参数传递给ENTRY(system_call),其中,定义res取得返回值,并将__NR_用##将其与name连接起来作为参数,这个参数定义在unistd.h的宏中,其它参数arg1,arg2,arg3则被存放在相应的寄存器ebx, ecx, edx中. 在“_syscallX”宏中,约定五个参数分别与五个寄存器对应:

arg1值存入寄存器ebx;

arg2值存入寄存器ecx;

arg3值存入寄存器edx;

arg4值存入寄存器esi;

arg5值存入寄存器edi;

另外, 若系统调用中出错,则将__res的相反数作为出错号赋给全局变量“errno”,并返回-1,否则返回__res 。

注意: 上面提到了汇编指令int 0x80 中断调用能跳转到ENTRY(system_call),这就不得不提到系统的中断矢量表, 在中断矢量表中,事先将int 0x80中断的指针指向了系统调用system_call, 正如下面提到的

1.3系统调用矢量表

在“/arch/i386/entry.S”中定义了系统调用表( sys_call_table ),保存了所有Linux基于Intel x86系列体系结构的计算机的系统调用入口地址, 核心入口指针ENTRY(system_call)对所有的系统调用都是相同的。它的作用是保存所有的寄存器值:

ENTRY(system_call)

pushl %eax # save orig_eax

SA VE_ALL

GET_CURRENT(%ebx)

cmpl $(NR_syscalls),%eax

jae badsys

testb $0x20,flags(%ebx) # PF_TRACESYS

jne tracesys

call *SYMBOL_NAME(sys_call_table)(,%eax,4)

movl %eax,EAX(%esp) # save the return value

ALIGN

.globl ret_from_sys_call

.globl ret_from_intr

首先用SA VE_ALL这个宏将所有的寄存器值都保存,并且检查确认该系统调用合法性, 然后用cmpl$( NR_syscalls ), %eax 来判断, 如果$(NR_syscalls )>=%eax (eax中存放的是当前的系统调用号),则超过了系统调用的最大限制, 违法. 跳至badsys:

movl $-ENOSYS,EAX(%esp)

jmp ret_from_sys_call

这段代码先将eat 中的出错码的相反数赋给ENOSYS , 再调用ret_from_sys_call 返回.

如果调用合法, ENTRY将控制权交至*SYMBOL_NAME (sys_call_table) (,%eax,4 ) ,eax 中的内容* 4 就是系统调用的实际地址偏移量. 通过它可找到相应的系统调用代码的:

.data

ENTRY(sys_call_table)

.long SYMBOL_NAME(sys_setup) /* 0 */

.long SYMBOL_NAME(sys_exit)

.long SYMBOL_NAME(sys_fork)

* * * * * *

.space (NR_syscalls-166)*4

在include/linux/sys.h 文件中定义了宏NR_systemcall,其值为256,表示x86微机上最多可容纳的系统调用个数。

我们已经介绍过了中断0x80 和系统调用表, 可以说已经了解了系统调用的一般流程, 下面就结合一个实例具体分析一下吧

二.系统调用实例exit 的分析

exit 系统调用简介:

正与fork 系统调用创建一个子进程相反, exit 的目的是为了撤销一个进程, 像上面系统调用表中提到的那样, 通过调用sys_exit( ) 函数终止一个进程的运行.处理期间, 要保存当前帐号的各种信息,逐步退出占用的资源, 还要处理好与之有关的其他进程.

2.1 exit 的简单流程

首先, 为了以下讨论方便, 我先将主要源码exit.c 中的一些代码附在下面, 并分别加上字母序号划分开来( NORET_TYPE 表示此为非停机类型):

NORET_TYPE void do_exit(long code)

{

(a) if (intr_count) {

printk("Aiee, killing interrupt handler\n");

intr_count = 0;

}

(b) fake_volatile:

a cct_process(code);

c urrent->flags |= PF_EXITING;

d el_timer(¤t->real_timer);

s em_exit();

k erneld_exit();

(c) __exit_mm(current);

__exit_files(current);

__exit_fs(current);

__exit_sighand(current);

e xit_thread();

(d) current->state = TASK_ZOMBIE;

c urrent->exit_code = code;

e xit_notify();

#ifdef DEBUG_PROC_TREE

a udit_ptree();

#endif

(e) if (current->exec_domain && current->exec_domain->use_count)

(*current->exec_domain->use_count)--;

i f (current->binfmt && current->binfmt->use_count)

(*current->binfmt->use_count)--;

(f) schedule();

g oto fake_volatile;

}

(g ) asmlinkage int sys_exit(int error_code)

{

d o_exit((error_code&0xff)<<8);

}

以上文件存放在/linux/kernel/ 目录下.

先看(g ) : Sys_exit的主体函数非常简单,只是调用了函数do_exit ( ), 其中(error_code&0xff)<< 8的作用就是取error_code的低8位移到高8位中( 低8位用0填补) 作为参数传给函数do_exit ( )。

下面来看看函数do_exit是怎样做的。

(a) 标注处: do_exit( ) 函数首先判断是否还有正在处理的中断服务( 若全局变量intr_count为1,表明当前还有中断正在处理). 如果有的话, 设置intr_count=0;停止处理其他中断。

(b) 标注处:

函数acct_process()定义在/linux/kernel/sys.c中, 限于篇幅, 此处并未列出, 其中定义了一个acct 结构类型变量 ac .acct 结构定义如下(在/linux/include/acct.h

文件中):

struct acct{charac_comm[ACCT_COMM]; /* 当前正在执行的命令*/ {charac_comm[ACCT_COMM]; /* 当前正在执行的命令*/

charac_comm[ACCT_COMM]; /* 当前正在执行的命令*/

time_t ac_utime; /* 当前的用户时间*/

time_t ac_stime; /* 当前的系统时间*/

time_t ac_etime; /* 本次登录到当前的时间差*/

time_t ac_btime; /* 本次开始时间 */

uid_t ac_uid; /* 对应用户的ID号*/

gid_t ac_gid; /* 对应用户所属组的ID号 */

dev_t ac_tty; /* 所在的终端号tty*/

char ac_flag; /* 标记,包括该用户的权限描述等 */

long ac_minflt; /* 次缺页情况 */

long ac_majflt; /* 主缺页情况*/

long ac_exitcode; /* 当前进程的退出代码*/

};

通过以上结构变量 ac , 保存当前账号的各种状态;

语句current->flags |= PF_EXITING 设置一标记,表明进程处于撤销状态;

语句del_timer( ¤t->real_timer) 目的是删除当前的实定时器:

语句Sem_exit()定义在/linux/ipc/sem.c文件中, 目的是删除信号队列(destroye semaphore arrays),释放信号撤消结构(free semaphores undo structures)在该函数中,增加调整值(semval)给信号,再释放撤消结构(free undo structures)。由于某些信号(semaphore)可能已经过时或无效了,直到信号数组(semaphore array)被删除了以后,撤消结构(undo structures)才被释放。具体做法如下:

a.如果当前进程正在睡眠状况(需要一信号(semaphore)来唤

醒),将进程当前指向所需信号(semaphore)的指针置空。

b.在当前的信号撤消链表(struct sem_undo)里查找a中提到的

那信号(semaphore),找到以后,调整该信号(已在信号撤消

链表中注册过的)的内容。

c.由于有可能有一个队列的进程在等该信号,故须更新整个操

作系统的数组。

语句kerneld_exit ( )清空当前任务的kerneld队列: 我们需要内”冲洗”一下所有的等待进程,以便于当那些进程结束时,do_exit函数可以减少一些独立的消息的可能性。因此,我们必须保证那些消息队列是空的,无论所有的kerneld是否已经死亡。

(c ) 标记处:

语句_exit_mm(current) 使进程退出内存管理系统,主要作以下工作:

1. 将cache,tlb,page的内容全部回写。

2. 退出内存影射。

3. 释放页表(page table)。

(d) 标注处:

语句current->state = TASK_ZOMBIE将当前进程的状态(state)设为TASK_ZOMBIE ( 即僵死状态) ;

语句current->exit_code=code设置退出码为传进来的参数code;

函数exit_notify()发送信号给进程所在的进程组( ”SIGHUP”

和”SIGCONT”信号) , 并且通知父进程,本进程已经被撤销了;然后进入一循环做以下两件事:

a.使初始进程(init)继承所有子进程。

b.检查是否还有进程组不是孤立的。如果是, 按照上面方法处

理;

最后,调用函数disassciate_ctty ( int) ( 定义在linux\drivers\char\tty_io.c

文件中)。只有当参数是1时,才是被exit_notify()调用的。在该函数中,将当前tty进程组杀掉,所有进程对应的tty成员赋NULL;

(e ) 标注处:

语句current->exec_domain指向进程所属的全局执行域结构,将所属用户数目减一;

( f) 继续调度:

schedule(); 正常情况下, 此函数将不再返回, 如果异常情况发生, 导致跳出, 使用goto fake_volatile 语句继续处理.

至此. Exit 的流程结束 . 下面是

2.2关于exit 的若干说明

首先 sys_exit 系统调用的宏定义可在文件/asm-i386/unistd.h下面找到很( 其他系统调用也包括在此文件中), sys_exit的具体定义如下:

static inline _syscall1(int,_exit,int,exitcode)

很明显exit 只使用一个参数, 将其展开后,形成代码如下:

int _exit(int exitcode)

{ long __res;

__asm__ volatile ("int $0x80"

: "=a" (__res)

: "0" (__NR_exit), "b" ((long)(exitcode)));

if (__res >= 0 )

return (int) __res;

errno = -__res;

return -1;

}

可以看出来,sys_exit带了参数exitcode,该参数便是系统退出(sys_exit)的退出码。正如前面第一章曾提到的那样, _exit通过调用int 0x80并传入系统调用号(_NR_exit,即在sys_call_table中的偏移量)和退出码(exitcode)的方法,来达到调用sys_exit的目的。

然后,当调用完sys_exit后,先判断返回值_res是否为非负数。若是,则说明该次调用是成功的,返回_res即可。若_res为负数,则说明该次调用过程中存在着一个或一些错误,将错误值赋给全局变量errno:

errno = -_res;(errno 即错误号)

同时返回-1,指明存在错误,由专门处理错误函数根据errno的值判断究竟系统调用出了什么错,是哪种类型的错,以便进行错误处理。

exit 系统调用整体说来流程并不复杂,甚至可以说是比较简单. 它用到不少低层函数,如__exit_mm(current);

__exit_files(current);

__exit_fs(current);

__exit_sighand(current);

等,这就大大减轻了自身函数的工作量,并使流程清晰. 顺便提一句,我认为以上几个函数源码很清晰明了,这里就不再细述了.

三实验小结

限于水平, 尽管努力的分析源代码, 还是有许多不明白的地方, 尤其是系统调用流程所用到的底层函数的细节. 对其设计的技巧和策略也尚未完全领会. 如exit 系统调用时使用到的goto fake_volatile 语句的必要性及具体作用方式还有疑虑. 而且, 由于自己英语水平不高, 对外籍资料和源码中的说明可能也有偏差, 希望得到大家的指正.谢谢!

本报告资料主要来源:《操作系统基础》(屠立德屠祈编著)以及浙大bbs 缥缈水云间有关版面。

linux实验_添加系统调用-完整版

实验一添加一个新的系统调用 一、实验目的 理解操作系统内核与应用程序的接口关系;加深对内核空间和用户空间的理解;学会增加新的系统调用。 二、实验内容与要求 首先增加一个系统调用函数,然后连接新的系统调用,重建新的Linux内核,用新的内核启动系统,使用新的系统调用(2.4内核和2.6内核任选一个) 三、实验指导(2.6版本) ⑴获得源代码(本次实验的内核版本是2.6.22.5,必须是root用户) 1.从教育在线上下载内核源代码到本地磁盘;保存在/usr/src目录下 2.进入终端,输入命令cd /usr/src 进入/usr/src目录(可以输入ls命令会发现目录下有一个名为LINUX_2_6_22_5.TAR.BZ2的压缩文件) 3.当前目录下(/usr/src)输入命令tar –xjvf LINUX_2_6_22_5.TAR.BZ2 解压缩源代码,命令执行完毕后,会出现/usr/src/linux-2.6.22.5文件夹 4.修改文件夹下的3个文件 第一,编辑/usr/src/linux-版本号/kernel/sys.c文件,添加函数: asmlinkage long sys_mycall(long number) { printk(“call number is %d\n”,number); return number; } 第二,修改/usr/src/linux-版本/include/asm-i386/unistd.h 添加一行#define __NR_mycall 324 到当前的最大系统调用号之后,比如原来最大的是323,在323的这一行之后加上一行#define __NR_mycall 324 修改#define NR_systemcalls 的值,改成原来的值+1,比如原来是324 改成325 第三,编辑/usr/src/linux-版本/arch/i386/kernel/syscall_table.S,在文件最后加上一行:.long sys_mycall 5.重新编译内核 在终端输入命令,进入源代码文件夹,cd /usr/src/linux-2.6.22.5 依次执行如下命令:make mrproper make clean make xconfig (自己配置内核,出现图形对话框后,直接点保存,关闭) make (耗时最长,大约20分钟) make modules_install (安装模块) 以上命令执行完毕后,会在当前目录下生成一个名为System.map的文件,会在/usr/src/linux-版本号/arch/i386/boot/下生成一个bzImage文件。

献给初学者:谈谈如何学习Linux操作系统

献给初学者:谈谈如何学习Linux操作系统 一、选择适合自己的linux发行版 谈到linux的发行版本,太多了,可能谁也不能给出一个准确的数字,但是 有一点是可以肯定的,linux正在变得越来越流行,面对这么多的Linux发行版,打算从其他系统转到linux系统来的初学者可能会感到困惑,即便是忠实的 Linux用户也没有时间和精力去挨个尝试,因此初学者在学习linux的之前,需 要有一个明确的方向,选择一个适合自己的系统开始学习linux至关重要!下面 我们就分类介绍。 1.1初学者入门首选-redhat系列 在学习redhat系列linux之前,首先要了解以下redhatlinux各个发行版本之 间的关系。 1.RedHatLinux RedHatLinux是redhat最早发行的个人版本的linux,其1.0版本于1994年11月3日发行。虽然其历史不及其它linux发行版本悠久,但比起很多的Linux 发行套件,RedHat的历史悠久得多。自从RedHat9.0版本发布后,RedHat公司就不再开发桌面版的Linux发行套件,RedHatLinux停止了开发,而将全部 力量集中在服务器版的开发上,也就是RedHatEnterpriseLinux版。2004年4 月30日,RedHat公司正式停止对RedHat9.0版本的支持,标志著RedHatLinux的正式完结。原本的桌面版RedHatLinux发行套件则与来自开源 社区的Fedora进行合并,成为FedoraCore发行版本。 目前RedHat分为两个系列:由RedHat公司提供收费技术支持和更新的RedHatEnterpriseLinux,以及由社区开发的免费的FedoraCore。 2.FedoraCore FedoraCore(缩写为FC)被红帽公司定位为新技术的实验场地,许多新的技 术都会在FC中检验,如果稳定的话红帽公司则会考虑加入RedHatEnterpriseLinux中。 FedoraCore1发布于2003年年末,而FC的定位便是桌面用户。FC提供了 最新的软件包,同时,它的版本更新周期也非常短,仅6个月。由于版本更新 频繁,性能和稳定性得不到保证,因此,一般在服务器上不推荐采用FedoraCore。 其实可以这么认为,Fedora就是RedHat发行RedHat企业版linux的一个 实验版本,以用户做测试,为RedHat企业版发布奠定基础。 3.RedHatEnterpriseLinux RedHatEnterpriseLinux(缩写为RHEL,RedHat的企业版)。RedHat现在主要做服务器版的linux开发,在版本上注重了性能和稳定性以及对硬件的支持。由于企业版操作系统的开发周期较长,注重性能、稳定性和服务端软件支持, 因此版本更新相对较缓慢。

linux系统编程试卷(答案)

凌阳教育 嵌入式培训系统编程部分测试试题 注:考试为闭卷,程序题需上机操作运行出结果,考试时间为120分钟 一:选择题(本题共4小题,每题3分共12分) 1)下列不是Linux系统进程类型的是( D ) A 交互进程 B 批处理进程 C 守护进程 D 就绪进程(进程状态) 2)以下对信号的理解不正确的是( B ) A 信号是一种异步通信方式 B 信号只用在用户空间进程通信,不能和内核空间交互 C 信号是可以被屏蔽的 D 信号是通过软中断实现的 3)进程有三种状态( C ) A 准备态、执行态和退出态 B 精确态、模糊态和随机态 C 运行态、就绪态和等待态 D 手工态、自动态和自由态 4)不是进程和程序的区别( B) A 程序是一组有序的静态指令,进程是一次程序的执行过程 B 程序只能在前台运行,而进程可以在前台或后台运行 C 程序可以长期保存,进程是暂时的 D 程序没有状态,而进程是有状态的 二:填空题(本题共6小题,2)、3)两题每空四分,其余每空一分。共23分) 1) 列举八种常见的进程间通信方式无名管道、有名管道、消息队列、信号量、共享内存、信号、套接字 网络上两个主机的进程间通信方式为套接字 2) 命名管道比无名管道的优势提供了一个可以访问的路径名,实现没亲缘关系的进程 间通信 3) 消息队列比命名管道和无名管道的优势可以按类型实现消息的随机查询,没必要先 进先出 4) 按照逻辑结构不同进行数据库划分,Sqlite 数据库属于哪一类关系型数据库 5) 在C语言中操作sqlite数据库,常用的2中方式是sqlite_exec(回调)、

sqlite_gettable(非回调) 6) 列举四种进程调度算法先来先调度(FCFS)、短进程优先调度(SPF)、高优先级调度 (HPF)、时间片轮转调度 三:问答题(本题共7题,每题5分,共35分) 1) 什么是系统调用?系统调用是通过什么方式陷入内核态的?请写出你对系统调用的理解。什么是文件I/O和标准I/O库?文件I/O和标准I/O库的区别? 系统调用是指操作系统提供给用户程序调用的一组特殊接口,用户程序可以通过这组接口获得操作系统内核提供的服务。 系统调用是通过软件中断方式陷入内核的 linux的文件I/O是由操作系统提供的基本IO服务, 标准I/O库通过封装系统调用,提供了一个到底层I/O的接口。 标准I/O默认采用了缓冲机制,还创建了一个包含文件和缓冲区相关数据的数据结构;文件I/O一般没有采用缓冲模式,需要自己创建缓冲区。一种是标准库封装系统调用而成,更高级,一种是系统提供的,比较低级;标准I/O可移植性高、文件I/O可移植性低。 2) 什么是进程?用fork()创建一个子进程时,系统会做什么工作 进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配的单位,不仅是系统内部独立运行的实体也是独立竞争资源的实体。 用fork()时系统会分配子进程一个ID号然后继承父进程的地址空间,包括进程上下文进程堆栈打开的文件描述符等等,他就是父进程的一个复制品。 3) 进程和线程有什么区别? 每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在进程程中,由进程提供多个线程执行的控制。 进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。 4) 什么是线程的互斥和同步,程序应怎样写才能达到互斥或同步? 互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。 同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。 在写程序时可以用互斥锁和信号量实现线程同步,一个线程访问共享资源时给这个资源上锁其他线程就不能访问了直到上锁的进程释放互斥锁为止。 5) 什么是僵尸进程?孤儿进程?守护进程? 僵尸进程:僵尸进程是指它的父进程已经退出(父进程没有等待(调用wait/waitpid)它),而该进程dead之后没有进程接受,就成为僵尸进程,也就是(zombie)进程。 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成

浅谈操作系统(操作系统论文)

浅谈操作系统 摘要 随着科学技术的不断发展与创新,计算机得到了广泛的普及和应用,同时计算机的操作系统也在不断的发展和完善当中。21世纪是信息的时代,最重要的体现就是计算机技术的广泛应用及发展,操作系统作为计算机系统的基础是管理计算机软硬件资源、控制程序运行、改善人机界面和为应用软件提供支持的一种系统,本文主要是通过对操作系统及其发展情况来进行分析,了解计算机操作系统发展的基本情况,阐述未来操作系统的发展趋势,从而促进计算机技术的不断的进步。 关键词:计算机;操作系统;发展; 一、计算机操作系统的发展史 操作系统是管理计算机硬件资源,控制其他程序运行并为用户提供交互操作界面的系统软件的集合。操作系统是计算机系统的关键组成部分,负责管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本任务。操作系统所处位置作系统是用户和计算机的接口,同时也是计算机硬件和其他软件的接口。 原始的操作系统主要是从批次模式开始,然后逐渐的发展到分时机制的模式,后来由于多处理器时代的到来,整个操作系统也逐渐有多处理器的协调功能,继而出现了分布式的系统。操作系统主要发展可分为四个阶段:纯手工操作阶段、批次处理阶段、多道程序系统阶

段及现代操作系统阶段。整个系统的发展主要面临着技术上的难题,主要体现的是计算机硬件技术的发展限制了软件的发展和操作系统的不稳定性。 二、计算机中常用的操作系统 计算机操作系统作为计算机系统的基础是管理电脑软硬件系统的程序。计算机系统的种类多,经常是通过应用领域来划分的,其中应用程序主要是包括桌面、服务器、主机以及嵌入几个应用领域的操作系统。常用的操作系统分类如下。 1.Windows系统 Windows系统作为计算机内较为常见的操作系统,在人们的日常生活和学习中都应用的较为普遍,Windows系统作为现代最为流行的操作系统,其在技术方面也是非常成熟的。目前最新版本的Windows 操作系统为Windows10。 2.UNIX系统 UNIX系统有自身较为统一的实施标准和认证规范,并且利用该规范,还可以对UNXI系统进行程序的移植,并且促进了UNIX的发展及应用程序的开发,UNXI已经开始作为大型机器、网络服务器及工作中的主流操作系统,并且其自身的发展还在一定的程度上推动了Linux等开源UNIX类操作系统的发展。 3.Linux系统 Linux系统是在UNIX的基础上进行发展的,其开源模式的软件环境极其价值越来越受到社会,并且其软件的运行环境及其价值越来

探究linux内核,超详细解析子系统

探究linux内核,超详细解析子系统 Perface 前面已经写过一篇《嵌入式linux内核的五个子系统》,概括性比较强,也比较简略,现在对其进行补充说明。 仅留此笔记,待日后查看及补充!Linux内核的子系统 内核是操作系统的核心。Linux内核提供很多基本功能,如虚拟内存、多任务、共享库、需求加载、共享写时拷贝(Copy-On-Write)以及网络功能等。增加各种不同功能导致内核代码不断增加。 Linux内核把不同功能分成不同的子系统的方法,通过一种整体的结构把各种功能集合在一起,提高了工作效率。同时还提供动态加载模块的方式,为动态修改内核功能提供了灵活性。系统调用接口用户程序通过软件中断后,调用系统内核提供的功能,这个在用户空间和内核提供的服务之间的接口称为系统调用。系统调用是Linux内核提供的,用户空间无法直接使用系统调用。在用户进程使用系统调用必须跨越应用程序和内核的界限。Linux内核向用户提供了统一的系统调用接口,但是在不同处理器上系统调用的方法

各不相同。Linux内核提供了大量的系统调用,现在从系统 调用的基本原理出发探究Linux系统调用的方法。这是在一个用户进程中通过GNU C库进行的系统调用示意图,系 统调用通过同一个入口点传入内核。以i386体系结构为例,约定使用EAX寄存器标记系统调用。 当加载了系统C库调用的索引和参数时,就会调用0x80软件中断,它将执行system_call函数,这个函数按照EAX 寄存器内容的标示处理所有的系统调用。经过几个单元测试,会使用EAX寄存器的内容的索引查system_call_table表得到系统调用的入口,然后执行系统调用。从系统调用返回后,最终执行system_exit,并调用resume_userspace函数返回用户空间。 linux内核系统调用的核心是系统多路分解表。最终通过EAX寄存器的系统调用标识和索引值从对应的系统调用表 中查出对应系统调用的入口地址,然后执行系统调用。 linux系统调用并不单层的调用关系,有的系统调用会由

linux 内存相关操作函数

Linux内核中内存相关的操作函数 1、kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) 内核空间申请指定大小的内存区域,返回内核空间虚拟地址。在函数实现中,如果申请的内存空间较大的话,会从buddy系统申请若干内存页面,如果申请的内存空间大小较小的话,会从slab系统中申请内存空间。 gfp_t flags 的选项较多。参考内核文件gfp.h. 在函数kmalloc()实现中,如果申请的空间较小,会根据申请空间的大小从slab中获取;如果申请的空间较大,如超过一个页面,会直接从buddy系统中获取。 2、vmalloc()/vfree() void *vmalloc(unsigned long size) 函数作用:从高端(如果存在,优先从高端)申请内存页面,并把申请的内存页面映射到内核的动态映射空间。vmalloc()函数的功能和alloc_pages(_GFP_HIGHMEM)+kmap() 的功能相似,只所以说是相似而不是相同,原因在于用vmalloc()申请的物理内存页面映射到内核的动态映射区(见下图),并且,用vmalloc()申请的页面的物理地址可能是不连续的。而alloc_pages(_GFP_HIGHMEM)+kmap()申请的页面的物理地址是连续的,被映射到内核的KMAP区。 vmalloc分配的地址则限于vmalloc_start与vmalloc_end之间。每一块vmalloc分配的内核虚拟内存都对应一个vm_struct结构体(可别和vm_area_struct搞混,那可是进程虚拟内存区域的结构),不同的内核虚拟地址被4k大小的空闲区间隔,以防止越界--见下图)。与进程虚拟地址的特性一样,这些虚拟地址与物理内存没有简单的位移关系,必须通过内核页表才可转换为物理地址或物理页。它们有可能尚未被映射,在发生缺页时才真正分配物理页面。 如果内存紧张,连续区域无法满足,调用vmalloc分配是必须的,因为它可以将物理不连续的空间组合后分配,所以更能满足分配要求。vmalloc可以映射高端页框,也可以映射底端页框。vmalloc的作用只是为了提供逻辑上连续的地址… 注意:在申请页面时,如果注明_GFP_HIGHMEM,即从高端申请。则实际是优先从高端内存申请,顺序为(分配顺序是HIGH, NORMAL, DMA )。 3、alloc_pages()/free_pages() 内核空间申请指定个数的内存页,内存页数必须是2^order个页。 alloc_pages(gfp_mask, order) 中,gfp_mask 是flag标志,其中可以为_ _GFP_DMA、_GFP_HIGHMEM 分别对应DMA和高端内存。

linux添加系统调用实验步骤

首先,进入到内核源码目录/usr/src/linux-2.6.34中,添加自己的系统调用号。 lyh@lyh:~$ cd /usr/src/linux-2.6.34/ 系统调用号在unistd_32.h文件中定义。内核中每个系统调用号都是 以“__NR_"开头的,在该文件中添加自己的系统调用号 lyh@lyh:/usr/src/linux-2.6.34$ sudo vim arch/x86/include/asm/unistd_32.h #define __NR_pwritev 334 #define __NR_rt_tgsigqueueinfo 335 #define __NR_perf_event_open 336 #define __NR_recvmmsg 337 #define __NR_mycall 338 #ifdef __KERNEL__ #define NR_syscalls 339 在内核源文件中该行为#define NR_syscalls 338,在系统调用执行的过程中,system_call()函数会根据该值来对用户态进程的有效性进行检查。如果这个号大于或等于NR_syscalls,系统调用处理程序终止。所以应该将原来的#define NR_syscalls 338修改为#define NR_syscalls 339 其次,在系统调用表中添加相应的表项 (1)lyh@lyh:/usr/src/linux-2.6.34$ sudo vim arch/x86/kernel/syscall_table_32.S ENTRY(sys_call_table) .long sys_restart_syscall .long sys_exit ………………(这里省略了部分) .long sys_rt_tgsigqueueinfo .long sys_perf_event_open .long sys_recvmmsg .long sys_mycall (2)lyh@lyh:/usr/src/linux-2.6.34$ sudo vim arch/h8300/kernel/syscalls.S #include #include

linux操作系统发展现状

Linux 操作系统发展现状 Linux操作系统发展迅速,全球Top500超级计算发布数据显示89.2%的超级计算机运行在Linux操作系统之上;桌面操作系统市场份额虽然不高,但也在逐年扩大;国际大公司Intel、Google、IBM等都在Linux操作系统上加大研发投入,为Linux 操作系统长远发展带来充足后劲。国内操作系统研发组织机构、厂商也都相应加大投入,以缩小与国际Linux 厂商技术之间的差距。 但是Linux 的发展仍然面临着兼容性差,软件缺乏,以及面临版本众多导致Linux 操作系统分裂等问题。掌握核心技术,解决Linux 当前面临的关键发展问题是当务之急。 一国内Linux 操作系统发展现状 国内目前涉足Linux操作系统研发除学校、研发机构外,主要Linux 发行版包括红旗、中标、共创、新华、拓林思等,均有桌面和服务器两个版本; 国内各发行版均基于国际社区版本发展而来,基于国际社区成果,在界面定制上做了一些工作,并没有掌握核心技术,且与国际Linux 操作系统发行版之间存在一定的技术差距,缺少技术积累,面临Linux发展后劲不足等问题。 二国外Linux 操作系统发展现状 国外主要发行版包括redhat、ubuntu、Suse 等,均提供桌面

和服务器两个不同版本。服务器领域Linux 操作系统发展比较成熟,桌面发展比较缓慢,嵌入式领域发展较快。 Redhat RHEL是目前Linux服务器产品的标杆,在国内和国际上都占据着主要的Linux 服务器市场份额。RHEL 产品功能全面,产品认证齐全,用户的接受度比较高。RHEL 主要依靠技术服务和产品维护获取盈利。Redhat自9.0以后,不再发布桌面版,而是把这个项目与开源社区合作,于是就有了Fedora这个Linux发行版。目前Fedora对于Redhat的作用主要是为RHEL提供开发的基础。Fedora 的界面与操作系统与RHEL 非常相似、用户会感觉非常熟悉;另外对于新技术,fedora一直快速引入;并且fedora 一直坚持绝对开源的原则。而因为Redhat 在Linux的地位和影响力,拥有很多坚定的爱好者使用。 Suse SLES被Novell收购以后,产品的竞争力获得了很大的提升。SLES最大的优势在于应用解决方案比较丰富。SLES同样依靠技术服务和产品维护获取盈利。SUSE的yast2配置工具一直是业内公认的非常完善的安装及系统工具,能够进行系统大多数的配置功能;另外,SUSE 与 67 微软的合作,也使得SUSE在与Windows的互操作性方面具

linux的system () 函数详解

linux的system () 函数详解 system(执行shell 命令) 相关函数 fork,execve,waitpid,popen 表头文件 #i nclude 定义函数 int system(const char * string)? 函数说明 system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命>令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。 返回值 =-1:出现错误 =0:调用成功但是没有出现子进程 >0:成功退出的子进程的id 如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值>。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。 附加说明 在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。 范例 #i nclude main() { system(“ls -al /etc/passwd /etc/shadow”)? } 执行结果: -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd -r--------- 1 root root 572 Sep 2 15 :34 /etc/shado 例2: char tmp[]? sprintf(tmp,"/bin/mount -t vfat %s /mnt/usb",dev)? system(tmp)? 其中dev是/dev/sda1。

Linux内核中增加一个系统调用

选题要求:在Linux内核中增加一个系统调用,并编写对应的linux应用程序。利用该系统调用能够遍历系统当前所有进程的任务描述符,并按进程父子关系将这些描述符所对应的进程id(PID)组织成树形结构显示。

目录 一.程序的主要设计思路,实现方式 (1) 1.1 添加系统调用的两种方法 (1) 1.1.1编译内核法 (1) 1.1.2内核模块法 (1) 1.2 程序的主要设计思路 (1) 1.3 环境 (2) 二.程序的模块划分,及对每个模块的说明 (2) 2.1 通过内核模块实现添加系统调用 (2) 2.1.1修改系统调用的模块 (2) 2.1.2获取sys_call_table的地址 (2) 2.1.3清除内存区域的写保护 (3) 2.2 编写系统调用指定自己的系统调用 (4) 2.2.1内核的初始化函数 (4) 2.2.2自己的系统调用服务例程 (4) 2.2.3移除内核模块时,将原有的系统调用进行还原 (6) 2.2.4模块注册相关 (6) 2.3 编写用户态的测试程序 (6) 2.4 编写Makefile文件 (7) 三.所遇到的问题及解决的方法 (8) 3.1 进程个数确定 (8) 3.2 被更改的系统调用号的选择 (8) 3.3 获取系统调用表的地址 (8) 3.4 内核和用户态数据交换 (8) 四.程序运行结果及使用说明 (8) 4.1 将编译出来的内核模块hello.ko加载到内核中 (8)

4.2通过dmesg查看输出信息是否正确 (9) 4.3运行测试程序,输出树状打印结果(部分结果截图) (9) 4.4卸载自定义模块 (10) 五.附录 (11) 5.1 内核模块程序hello.c (11) 5.2 测试程序hello_test.c (14) 5.3Makefile文件 (14)

浅谈我对计算机操作系统的认识

浅谈我对计算机操作系统的认识 朱雪松 L11214018 信息管理与信息系统 计算机的发展将趋向超高速、超小型、并行处理和智能化。自从1944年世界上第一台电子计算机诞生以来,计算机技术迅猛发展,传统计算机的性能受到挑战,开始从基本原理上寻找计算机发展的突破口,新型计算机的研发应运而生。未来量子、光子和分子计算机将具有感知、思考、判断、学习以及一定的自然语言能力,使计算机进人人工智能时代。这种新型计算机将推动新一轮计算技术革命,对人类社会的发展产生深远的影响。 一.什么是操作系统 操作系统(英语:Operating System,简称OS)是一管理电脑硬件与电脑软件资源的程序,同时也是计算机系统的核心与基石。操作系统身负诸如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网上与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作接口。 操作系统的型态非常多样,不同机器安装的操作系统可从简单到复杂,可从手机的嵌入式系统到超级电脑的大型操作系统。许多操作系统制造者对它涵盖范畴的定义也不尽一致,例如有些操作系统集成了图形化用户界面,而有些仅使用文字接口,而将图形接口视为一种非必要的应用程序. 二.操作系统的历史 (一)无操作系统的计算机系统 1.人工操作方式 从第一台计算机诞生(1945年)到20世纪50年代中期的计算机,属于第一代计算机,这一时期的计算机操作采用人工操作的方式直接使用计算机硬件系统,这种方式的主要特征是用户独占主机,CPU等待人工操作。可见这种方式严重降低了计算机资源的利用率,造成了人机矛盾。 2.脱机输入/输出方式 为了解决人机矛盾及CPU和I/O设备之间速度不匹配的矛盾,20世纪50年代末出现了这种技术。该技术是事先将装有用户程序和数据的纸带装入纸带输入机,在一台外围机的控制下,把纸带上的数据输入磁带上。当CPU需要这些程序和数据时,再从磁带上将其高速的调入内存。 (二)单道批处理系统和多道批处理系统 1.单道批处理系统的处理过程及特征 上个世纪50年代中期发明了晶体管,为了充分利用晶体管,减少空闲时间,于是就出现了单道批处理,其自动处理过程是:首先,由监督程序将磁带上的第一个作业装入内存,并把运行控制权交给该作业。当该作业处理完时,把控制权还给监督程序,再由监督程序把磁盘上的第二个作业调入内存。其主要特征为自动,顺序,单道。其主要矛盾为主机和外设的矛盾。

Linux系统调用详解之pdbedit

Name pdbedit ? manage the SAM database (Database of Samba Users) Synopsis pdbedit [?a] [?b passdb?backend] [?c account?control] [?C value] [?d debuglevel] [?D drive] [?e passdb?backend] [?f fullname] [??force?initialized?passwords] [?g] [?h homedir] [?i passdb?backend] [?I domain] [?K] [?L] [?m] [?M SID|RID] [?N description] [?P account?policy] [?p profile] [??policies?reset] [?r] [?s configfile] [?S script] [?t] [??time?format] [?u username] [?U SID|RID] [?v] [?V] [?w] [?x] [?y] [?z] [?Z] DESCRIPTION This tool is part of the samba(7) suite. The pdbedit program is used to manage the users accounts stored in the sam database and can only be run by root. The pdbedit tool uses the passdb modular interface and is independent from the kind of users database used (currently there are smbpasswd, ldap, nis+ and tdb based and more can be added without changing the tool). There are five main ways to use pdbedit: adding a user account, removing a user account, modifing a user account, listing user accounts, importing users accounts. OPTIONS ?L|??list This option lists all the user accounts present in the users database. This option prints a list of user/uid pairs separated by the ′:′ character. Example: pdbedit ?L sorce:500:Simo Sorce samba:45:Test User ?v|??verbose This option enables the verbose listing format. It causes pdbedit to list the users in the database, printing out the account fields in a descriptive format. Example: pdbedit ?L ?v

Linux操作系统学习心得

Linux操作系统学习心得 这学期有幸学习了《嵌入式系统设计》这门课,在胡佳文老师的教导下深入了解了有关于嵌入式系统,ARM9,Linux系统等很多方面的知识,获益良多,在学习过程中自己也遇到了很多问题,同时受到了很大的启发,现在就本学期的学习谈谈自己的学习心得体会。 Linux操作系统这个名词记得在很早以前就听过,知道这是一个开放性很大的系统,源代码是直接公布在互联网上,很多计算机高手可以根据自己的需求来修改这个程序,同时它比较不易死机,在自己的印象中一直是一种高大上的系统,但是更深入的了解确是零,对于这个学期选这门公共选修课,很大一部分原因是怀着一颗要了解一种早就想知道的东西的心选的.当然我平时也喜欢玩点电脑什么的,只是停留在用别人设计好的现成的东西。 经过一个学期linux操作系统的学习,在老师在课堂对linux系统的介绍及通过网络的了解下,知道了linux原来是一种和windows差不多的电脑操作系统,windows是图形界面的,linux类似以前的DOS,是文本界面的,如果你运行了图形界面程序X-WINDOWS后,linux也能显示图形界面,也有开始菜单、桌面、图标等。Windows有MS-DOS方式,在该方式下通过输入DOS命令来操作电脑;而linux与windows类似,也有命令方式,linux 启动后如果不执行X-WINDOWS,就会处于命令方式下,必须发命令才能操作电脑。另外linux上也有很多的应用软件,安装运行了这些软件后,你就可以在linux上编辑文档、图片,玩游戏、上网、播放多媒体文件等。 当然我们对linux的学习首先是通过对它的产生,发展,到今天仍然在不断完善开始的。它的产生和需要花钱买得windows系统形成了对比,因为 linux 的核心是免费的,自由使用的,核心源代码是开放的.任何人都可以根据自己的喜好来编辑创作适合自己的操作系统,linux是抢占式多任务多用户操作系统,Linux最大的优点在于其作为服务器的强大功能,同时支持多种应用程序及开发工具,所以linux操作系统有着广泛的应用空间。 而且在课上随着老师的讲解和自己动手查资料,慢慢的学习到了更深入的知识,知道了linux的安装:硬盘安装及光盘安装,清楚了解安装Linux应注意的有关问题。学习了linux系统的进入,关闭和重启。掌握了linux系统的硬件配置,如显卡,声卡,网卡等,并且通过对linux系统基本命令的学习,尤其是shell命令语言(亦称命令解释器),熟悉了系统的基本操作。当然在学习中发现英文学得好也是学好linux的关键。同时还了解了linux对应下的一些常用软件及这些软件的安装。因为linux在服务器中广泛的应用,于是我们进一步学习了linux下接入internet的WEB服务器的安装与配置方法。之后还了解了linux的网络安全,系统的安全,用户的安全等。 眼看这个学期Linux的课程已经告一段落了,在这段时间的学习如果要问我在这门课中学到了什么,我觉得是一种为学的方法,使我受益非浅。 首先每学一部分内容前必定有很多疑问,想要独立解开疑问,从网络上找资

8第八章Linux下的系统调用

第八章 Linux下的系统调用 8.1 系统调用介绍 8.1.1 引言 系统调用是内核提供的、功能十分强大的一系列函数。它们在内核中实现,然后通过一定的方式(库、陷入等)呈现给用户,是用户程序与内核交互的一个接口。如果没有系统调用,则不可能编写出十分强大的用户程序,因为失去了内核的支持。由此可见系统调用的地位举足轻重。内核的主体可以归结为: 系统调用的集合; 实现系统调用的算法。 8.1.2 系统调用的实现流程 这里我们通过getuid()这个简单的系统调用来分析一下系统调用的实现流程。在分析这个程序时并不考虑它的底层是如何实现的,而只需知道每一步执行的功能。 首先来看一个例子: #include /* all system call need this header*/ int main() { int i=getuid(); printf(“Hello World! This is my uid: %d\n”,i); } #include是每个系统调用都必须要的头文件,当系统执行到getuid()时,根据unistd.h中的宏定义把getuid()展开。展开后程序把系统调用号__NR_getuid(24)放入eax,然后通过执行“int $0x80”这条指令进行模式切换,进入内核。int 0x80指令由于是一条软中断指令,所以就要看系统规定的这条中断指令的处理程序是什么。 arch/i386/kernel/traps.c set_system_gate(SYSCALL_VECTOR,&system_call); 从这行程序我们可以看出,系统规定的系统调用的处理程序就是system_call。控制转移到内核之前,硬件会自动进行模式和堆栈的切换。现在控制转移到了system_call,保留系统调用号的最初拷贝之后,由SAVE_ALL来保存上下文,得到该进程结构的指针,放在ebx里面,然后检查系统调用号,如果__NR_getuid(24)是合法的,则根据这个系统调用号,索引sys_call_table,得到相应的内核处理程序:sys_getuid。执行完sys_getuid之后,保存返回值,从eax移到堆栈中的eax处,假设没有

qt4中如何调用C函数(linux下)

qt默认的编程语言为C++语言。如果你用qt编译.c文件,会出现找不到C语言的默认头文件等错误(如:stdio.h等)。qt中不支持 extern "C"{}的这种写法,我前几天有一个C程序需要移植到Qt的工程中,本希望直接extern "C"就ok了,但发现qt4居然不支持这种写法。我的程序中用到了好几个linux系统头文件,是向串口发指令之类的程序,程序中用到了互斥锁并创建了一个线程。如果再用qt语言来写一遍的话我会挂掉的,所以没有办法,在网上找了半天,终于找到解决方法。 将.c文件编译为函数库的方式在qt下调用,这种方法貌似行得通,我就开始行动了。 下面的内容讲得比较多,比较全,比较适合初学者,是我在网上down的,给出了原网站的链接,最后给出了一个程序。经过自己整理好归纳如下: 需要说明的是:使用gcc可以将程序编译成动态库或者静态库的形式,它们在程序中的调用的方式也不尽相同,给出的程序中调用的是动态连接库。编译成动态的还是静态的根据自己的需要进行。如果原C程序编译的时候需要gcc的额外选项(如gcc -lpthread -o hello hello.c)等,建议采用动态的形式。 1.什么是静态连接库,什么是动态链接库 静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的EXE 文件中了。但是若使用DLL,该DLL 不必被包含在最终EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与EXE 独立的DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。在windows和linux上都是相同的,只不过文件的格式不同而已。 https://www.360docs.net/doc/f88591090.html,/winston/archive/2008/07/05/1236273.html 2.gcc生成静态库和动态库 第1步:编辑得到举例的程序--hello.h、hello.c和main.c; 第2步:将hello.c编译成.o文件;

linux系统调用

2002 年 3 月 01 日 本文列出了大部分常见的Linux系统调用,并附有简要中文说明。 以下是Linux系统调用的一个列表,包含了大部分常用系统调用和由系统调用派生出的的函数。这可能是你在互联网上所能看到的唯一一篇中文注释的Linux系统调用列表,即使是简单的字母序英文列表,能做到这么完全也是很罕见的。 按照惯例,这个列表以man pages第2节,即系统调用节为蓝本。按照笔者的理解,对其作了大致的分类,同时也作了一些小小的修改,删去了几个仅供内核使用,不允许用户调用的系统调用,对个别本人稍觉不妥的地方作了一些小的修改,并对所有列出的系统调用附上简要注释。 其中有一些函数的作用完全相同,只是参数不同。(可能很多熟悉C++朋友马上就能联想起函数重载,但是别忘了Linux核心是用C语言写的,所以只能取成不同的函数名)。还有一些函数已经过时,被新的更好的函数所代替了(gcc在链接这些函数时会发出警告),但因为兼容的原因还保留着,这些函数我会在前面标上“*”号以示区别。 一、进程控制: fork 创建一个新进程 clone 按指定条件创建子进程 execve 运行可执行文件 exit 中止进程 _exit 立即中止当前进程 getdtablesize 进程所能打开的最大文件数 getpgid 获取指定进程组标识号 setpgid 设置指定进程组标志号 getpgrp 获取当前进程组标识号 setpgrp 设置当前进程组标志号 getpid 获取进程标识号 getppid 获取父进程标识号 getpriority 获取调度优先级 setpriority 设置调度优先级 modify_ldt 读写进程的本地描述表 nanosleep 使进程睡眠指定的时间 nice 改变分时进程的优先级 pause 挂起进程,等待信号 personality 设置进程运行域 prctl 对进程进行特定操作 ptrace 进程跟踪 sched_get_priority 取得静态优先级的上限 _max sched_get_priority 取得静态优先级的下限 _min sched_getparam 取得进程的调度参数 sched_getscheduler 取得指定进程的调度策略 sched_rr_get_inter 取得按RR算法调度的实时进程的时间片长度 val sched_setparam 设置进程的调度参数 sched_setscheduler 设置指定进程的调度策略和参数

Linux系统API函数手册簿

(一)文件操作篇 1、creat(建立文件) 头文件 1 #include 2 #include 3 #include 定义函数 1int creat(const char * pathname, mode_tmode); 函数说明 参数pathname指向欲建立的文件路径字符串。creat()相当于使用下列的调用方式调用open() 1 open(const char * pathname ,(O_CREAT|O_WRONLY|O_TRUNC)); 错误代码 关于参数mode请参考open()函数。 返回值 creat()会返回新的文件描述词,若有错误发生则会返回-1,并把错误代码设给errno。EEXIST 参数pathname所指的文件已存在。 EACCESS 参数pathname 所指定的文件不符合所要求测试的权限 EROFS 欲打开写入权限的文件存在于只读文件系统内 EFAULT 参数pathname 指针超出可存取的内存空间 EINVAL 参数mode 不正确。 ENAMETOOLONG 参数pathname太长。 ENOTDIR 参数pathname为一目录 ENOMEM 核心内存不足 ELOOP 参数pathname有过多符号连接问题。 EMFILE 已达到进程可同时打开的文件数上限 ENFILE 已达到系统可同时打开的文件数上限 附加说明 creat()无法建立特别的装置文件,如果需要请使用mknod()。 2、open(打开文件) 头文件 1 #include 2 #include 3 #include 定义函数

相关文档
最新文档