lth文件怎么转换


    系统调用是应用程序(运行库也是应用程序的一部分)与操作系统内核之间的接口,它决定了应用程序如何与内核打交道。无论程序是直接调用系统调用还是通过运行库,最终还是会到达系统调用这个层面上。
    为了让操作系统有能力访问系统资源,也为了让程序借助操作系统做一些由操作系统支持的行为,每个操作系统都会提供一套接口,以供应用程序使用。这些接口往往通过中断来实现,比如Linux使用0x80号中断作为系统调用的入口,Windows采用0x2E号中断作为系统调用入口。
    下面我们来看看Linux系统调用的定义。在x86下,系统调用由0x80中断完成,各个通过寄存器用于传递参数,EAX寄存器用于表示系统调用的接口号,比如EAX = 1表示退出进程(exit);EAX = 2表示创建进程(fork);EAX = 3表示读取文件或IO(read);EAX = 4表示写文件或IO(write)等,每个系统调用都对应于内核源代码中的一个函数,它们都是以“sys_”开头的,比如exit调用对应内核中的sys_exit函数。当系统调用返回时,EAX作为调用结果的返回值。
    我们可以使用Linux的man命令查看每个系统调用的详细说明,比如查看read(man参数2表示系统调用手册):

    现代的CPU常常可以在多种截然不同的特权级别下执行指令,在现代操作系统中,通常也有两种特权级别,分别为用户模式(User Mode)和内核模式(Kernel Mode),也被称为用户态和内核态。
    系统调用是运行在内核态的,而应用程序基本都是运行在用户态的。用户态的程序如何运行内核态的代码呢?操作系统一般是通过中断(Interrupt)来从用户态切换到内核态。
    什么是中断呢?中断是一个英俊或软件发出的请求,要求CPU暂停当前的工作转手去处理更加重要的事情。
中断一般具有两个属性,一个称为中断号,一个称为中断处理程序。不同的中断具有不同的中断号,而同时一个中断处理程序一一对应一个中断号。在内核中,有一个数组称为中断向量表,这个数组的第n项包含了指向第n号中断的处理程序指针。当中断到来时,CPU暂停当前执行的代码,根据中断的中断号,在中断向量表中找到对应的中断处理程序,并调用它。中断处理程序执行完成以后,CPU会继续执行之前的代码。一个简单的示意图如下图所示。
    通常意义上,中断有两种类型,一种称为硬件中断,这种中断来自于硬件的异常或者其他事件的发生,如电源掉电、键盘被按下等。另一种称为软件中断,软件中断通常是一条指令(i386下是int),带有一个参数记录中断号,使用这条指令用户可以手动触发某个中断并执行期中断处理程序。例如在i386下,int 0x80这条指令会调用第0x80号中断的处理程序。
    由于中断是有限的,OS不会舍得用一个中断号来对应一个系统调用,而更倾向于用一个或少数几个中断号来对应所有的系统调用。例如,i386下Windows里绝对多数系统调用都是由int 0x2E来触发的,而Linux则使用int 0x80来触发所有的系统调用。
对于同一个中断号,操作系统如何知道哪一个系统调用被调用呢?和中断一样,系统调用都有一个系统调用号,就像身份标识一样来表明是哪一个系统调用,这个系统调用号通车就是系统调用在系统调用表中的位置,例如Linux里fork的系统调用号是2。这个系统调用号在执行int指令前会被放置在某个固定的寄存器中,对应的中断代码会取得这个系统调用号,并且调用正确的函数。以Linux的int 0x80为例,系统调用号是由eax来传入的。用户将系统调用号放入eax,然后使用int 0x80调用中断,中断服务器程序就可以从eax里面取得系统调用号,进而调用对应的函数。

四、基于int的Linux的经典系统调用实现
    下面我们将了解当应用程序调用系统时,程序是如何一步步进入操作系统内核调用相应函数的。下图是以fork为例的Linux系统调用的执行流程。
    解下来,让我们一步一步地了解这个过程的细节。
    首先,当程序在代码里调用一个系统调用时,是以一个函数的形式调用的,例如程序调用fork:

    fork函数是一个对系统调用fork的封装,可以用下列宏来定义它:
这个宏用于检查系统调用的返回值,并把它相应的转换为C语言的errno错误码。在Linux里面,系统调用使用返回值传递错误码,如果返回值为负数,那么表明调用失败,返回值的绝对值就是错误码。而在C语言里则不然,C语言里的大多数函数都是以返回-1表示调用失败,而将出错信息存储在一个名为errno的全局变量(在多线程库中,errno存储在TLS中)里。__syscall_return就负责将系统调用的返回值存储在errno中。这样,fork函数在汇编之后,就会形成类似如下的汇编代码:
    如果系统调用本身有参数要如何实现呢?下面是x86Linux下的syscall,用于带1个参数的系统调用:
    这段代码和_syscall0不同的是,它多了一个"b"((long)(arg1))。这一句的意思是先把arg1强制转换为long,然后放在EBX(b代表EBX)里作为输入。编译器还会生成相应的代码来保护原来的EBX的值不被破坏。这段汇编可以改写为:
    可见,如果系统调用有1个参数,那么参数通过EBX来传入。x86下Linux支持的系统调用参数至多有6个,分别使用6个寄存器来传递,它们分别是EBX、ECX、EDX、ESI、EDI和EBP。
    当用户调用某个系统调用时,实际上是执行了上面一段汇编代码。CPU执行到int $0x80时,会保存现成以便恢复,接着会将特权状态切换到内核态。然后CPU便会查找中断向量表中的第0x80号元素。
    以上是Linux实现系统调用入口的思路,不过也许你会想知道glibc是否真的是如此封装函数调用呢?答案是否定的。glibc使用了另外一套调用系统调用的方法,尽管原理上仍然是使用0x80号中断,但细节上却是不一样的。由于这种方法与上面的方法本质上是一样的,所以这里不介绍了。

在实际执行中断向量表中的第0x80号元素所对应的函数之前,CPU首先还要进行栈切换。在Linux中,用户态和内核态使用的是不同的栈,两者各自负责各自的函数调用,互不干扰。但在应用程序调用0x80号中断时,程序的执行流程从用户态切换到内核态,这时程序的当前栈必须也相应地从用户栈切换到内核栈。从中断处理函数中返回时,程序的当前栈还有从内核栈切换回用户栈。
    所谓的“当前栈”,指的是ESP的值所在的栈空间。如果ESP的值位于用户栈的范围内,那么程序的当前栈就是用户栈,反之亦然。此外,寄存器SS的值还应该指向当前栈所在的页。所以,将当前栈由用户栈切换到内核栈的实际行为就是:
    反过来,将当前栈的内核栈切换为用户栈的实际行为则是:
    (2)用户态的ESP和SS的值保存到哪里呢?答案就是内核栈上。这一行为由i386的中断指令自动地由硬件完成。
    当0x80号中断发生的时候,CPU除了切入内核态以外,还自动完成下列几件事:
    (1)找到当前进程的内核栈(每个进程都有自己的内核栈);
    而当内核从系统调用中返回的时候,需要调用iret指令返回到用户态,iret指令则会从内核栈里弹出寄存器SS、ESP、EFLAGS、CS、EIP的值,使得栈恢复到用户态的状态,这个过程可以用下图来表示。
    在int指令合理的切换了栈之后,程序的流程就切换到了中断向量表中记录的0x80号中断处理程序。Linux内部的i386中断服务流程如下图所示。
    从这段代码可以看到0-19号中断对应的中断处理程序,其中包含算数异常(除零、溢出)、页缺失、无效指令等。在最后一行:
    4上的那个元素的值指向的函数,也就是%eax所记录的系统调用号所对应的系统调用函数。接下来系统就会去调用相应的系统调用函数。例如,如果%eax = 2,那么sys_fork就会被调用。
    问题:内核以sys开头的系统调用函数是如何从用户那里获得参数的?
    答案:我们知道用户调用系统调用时,根据系统调用参数数量的不同,依次将参数放入EBX、ECX、EDX、ESI、EDI和EBP这6个寄存器中传递。例如一个参数的系统调用就是用EBX,而两个参数的系统调用就使用EBX和ECX,以此类推。
    而进入系统调用的服务程序system_call的时候,system_call调用了一个宏SAVE_ALL来保存各个寄存器。SAVE_ALL实际与系统调用的参数传递息息相关,所以这里有必要提一下。
    SAVE_ALL的作用为保存寄存器,因此其内容就是讲各个寄存器压入栈中。SAVE_ALL的大致内容如下:
    抛开SAVE_ALL的最后3个move指令不看(这3条指令用于设置内核数据段,它们不影响栈),我们可以发现SAVE_ALL是一系列push指令的最后6条所压入栈的寄存器恰好就是用来存放系统调用参数的6个寄存器,连顺序都一样,这当前不少一个巧合。
    再回到system_call的源码,可以发现,在执行SAVE_ALL与执行call *sys_call_table(0, %eax, 4)之间,没有任何代码会影响栈。因此刚刚进入sys开头的内核系统调用函数的时候,栈上恰恰是这样的情景,如下图所示。
    可以说,系统调用的参数被SAVE_ALL“阴差阳错”放置在了栈上。
    这个扩展关键字的意义是让这个函数只从栈上获取参数。因为gcc对普通函数有优化措施,会使用寄存器来传递参数,而SAVE_ALL将参数全部放置于栈上,因此必须使用asmlinkage来强迫函数从栈上获取参数。这样一来,内核里的系统调用函数就可以正确地获取用户提供的参数了。整个过程如下图所示。

怎样将一个xml文件转换为txt文件

或者你先用一个数据集读取XML文件,
再通过循环导出到文本文件中去。

说实话,楼上各位的大概思想我都明白,但是没有专门学面向对象,对类没什么理解.拿到手里,就不知道该怎么写了。
各位有没有相关代码,让我参考一下?

就是楼上的意思,我用richtextbox就可以把XML文件打开,但是没有去掉标记。
想要的结果是去掉标记后,不太明白楼上说的意思,我再好好看看。
把txt转程XML有可能吗?


昏倒,要是你不想改变内容,那就直接把扩展名改成 .txt不就完了!

致于只想要XML文件中的内容,想去掉那些分层的XML标记的话,你可以用 XMLDOM通过循环把XML文件中的内容读出来,用FileStream和StreamWriter类写到一个文本文件中去就行了。
。NET中操纵XML的类和DOM中相关不太,你可以看看。NET中关于操纵XML文档的帮助部分,再看看 IO 的文件操作部份,应该两三个小时就可以搞定的吧。如果你只是想做这点点小事的话。

今天继续分析无线驱动不能起来的问题,和几个同事交流后,测量出无线起来需要大概的内存量为9140KByte,而843v2的板上空余大概是7690KB,严重不足,而且webserver起来居然需要12752KB,这个太惊人了。

对wifid中qca目录,要实现对参数的读操作,参考mtk方案的数据格式和api,实现qca的api。

1.将只读的全局变量,加上const,从而使其转移到代码段;

3.减少全局变量的尺寸;

减少死代码,编译时带上-Wall 选项,去除unused variable 'i'之类的警告,有助于减少代码段占用的内存;

线程退出后,进程需要调用函数pthread_join结束,否则为每个线程分配的栈空间不会释放;

Linux内核中文件预读算法:对于每个文件的第一个请求,系统读入所请求的页面并读入紧随其后的少数几个页面,一般是3个;这个预读成为同步预读,对于第二次请求,如果所读页面不在Cache中,既是不在前次预读的group中,则表明文件访问不是顺序访问,系统继续采用同步预读; 如果所读页面在cache中,则表明预读命中,操作系统把预读group扩大一倍,并杨底层文件系统读入group中剩下不在Cache中的文件数据块,这是的预读成为异步预读。 

Killer)。当分配内存失败的时候LMR会将会起作用,失败的原因是kswapd不能提供足够的空余内存,这时LMR每次释放1024个垃圾页直到内存分配成功。当LMR不能快速释放内存的时候,OMK就开始起作用,OMK会采用一个选择算法来杀死某些今晨。当选定进程时,就会发送SIGKILL信号,这就会使内存立即被释放。OMK选择进程的方法:

1)进程占用大量的内存;

2)进程只会损失小量工作;

3)进程具有低的静态优先级;

4)进程不属于root用户;

连接运算符##可以把两个独立的字符串连接成一个字符串。

将main函数的参数复制,当中使用了二维指针,值得学习

栈是存放函数所有动态局部变量和函数调用和返回的有关信息的一块内存;堆是供malloc,calloc和realloc等函数获取内存空间的一块内存;

把数组传给函数时,有值传递和地址传递两种方式,在值传递方式中,在说明和定义函数时,要在数组参数的尾部加上一对方括号([]),调用函数只需要将数组的地址(数组名)传递给函数。

数组名不能被放在赋值运算符的左边,一个数组是一个对象,数组名就是指向这个对象的第一个元素的指针。

在jenkins中svn链接中增加@HEAD,可以不用理会服务器时间,直接更新到最新的版本

802.11n标准中采用A-MPDU聚合帧格式,即将多个MPDU聚合为一个A-MPDU,只保留一个PHY头,删除其余MPDU的PHY头,减少了传输每个MPDU的PHY头的附加信息,同时也减少了ACK帧的数目,从而降低了协议的负荷,有效的提高网络吞吐量

Makefile 下删除目录中所有的某类型文件

我要回帖

更多关于 LTH是什么缩写 的文章

 

随机推荐