Linux应用编程基础学习_第1页
Linux应用编程基础学习_第2页
Linux应用编程基础学习_第3页
Linux应用编程基础学习_第4页
Linux应用编程基础学习_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

-.z.Linu*下开发根底知识touch命令:可用于新建文件,如;touch/tmp/zhang*ian.t*t关于volatile的介绍(类型修饰符,指令关键字)1.编译器优化介绍由于存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行,没有相关性的指令可以乱序执行,以充分利用CPU的指令流水线,提高执行速度。以上是硬件级别的优化。再看软件一级的优化:一种是在编写代码时由程序员优化,另一种是由编译器进展优化。编译器优化常用的方法有:将存变量缓存到存放器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令。对常规存进展优化的时候,这些优化是透明的,而且效率很好。由编译器优化或者硬件重新排序引起的问题的解决方法是在从硬件〔或者其他处理器〕的角度看必须以特定顺序执行的操作之间设置存屏障〔memorybarrier〕,linu*提供了一个宏解决编译器的执行顺序问题。2.voidBarrier(void)这个函数通知编译器插入一个存屏障,但对硬件无效,编译后的代码会把当前CPU存放器中的所有修改正的数值存入存,需要这些数据的时候再重新从存中读出。3.volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以消除一些代码。但有时这些优化不是程序所需要的,这时可以用volatile关键字制止做这些优化。gccandg++分别是GNU的c&c++编译器。gcc/g++在执行编译的时候一般有下面4步:⒈预处理,生成.i的文件[预处理器cpp];⒉将预处理后的文件转换成汇编语言,生成文件.s[编译器egcs];⒊由汇编变为目标代码〔机器代码〕生成.o的文件[汇编器as];⒋连接目标代码,生成可执行程序[器ld];gcc编译流程分为4个步骤,分别为:预处理〔Pre-Processing〕编译〔piling〕汇编〔Assembling〕〔Linking〕g++-o-c-g功能-o:指定生成可执行文件的名称。使用方法为:g++-oafilefile.cppfile.h...〔可执行文件不可与待编译或文件同名,否则会生成相应可执行文件且覆盖原编译或文件〕,如果不使用-o选项,则会生成默认可执行文件a.out。-c:只编译不,只生成目标文件。-g:添加gdb调试选项。Linu*下C语言应用编程文件I/O编程多进程编程的根本知识,核心是fork、e*ec、wait三大系统的调用;〔可能需要补充操作系统进程并发运行的根本知识〕进程间通信的几种方法:信号,管道,共享存,信号量,消息队列。〔最重要的是信号和管道〕多线程编程的根底知识;网络编程:socket编程,TCPsocket编程和UDPsocket编程;开发工具〔包括:编辑器vim、编译器gcc、调试器gdb、工程管理工具autoconf、程序库的制作等〕;编译器vim的三种模式:切换到编辑模式的四种方式,编辑模式可以输入任意容a光标向后移动一位i

当前位置o另起新行s删除光标所在字符r替换光标所在字符2.尾行模式,用于保存容、查找替换、设置行号等等功能性操作:q

//quit退出vi编辑器:w//write保存修改的容:wq//保存并退出:q!//强制退出,当对文本容作了修改而不想要保存时:w!//强制保存,当没有文本的写权限时make和makefile文件:makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进展更复杂的功能操作〔因为makefile就像一个Shell脚本一样,可以执行操作系统的命令〕。makefile带来的好处就是—“自动化编译〞,一旦写好,只需要一个make命令,整个工程完全自动编译。makefile文件需要按照*种语法进展编写,文件中需要说明如何编译各个源文件并生成可执行文件,要求定义源文件之间的依赖关系。make工具最主要也最根本的功能就是根据makefile文件中描述的源程序之间的相互关系来完成自动编译、维护多源文件工程。Linu*下的常用命令Linu*删除文件夹和文件的命令-r就是向下递归,不管有多少级目录,一并删除-f就是直接强行删除,不作任何提示的意思删除文件夹实例:rm-rf/var/log/d/access将会删除/var/log/d/access目录以及其下所有文件、文件夹删除文件使用实例:rm-f/var/log/d/access.log将会强制删除/var/log/d/access.log这个文件文件I/O编程:系统调用、API与系统命令之间的关系Linu*系统调用是指操作系统提供应用户程序的一组“特殊〞接口,用户程序可以通过这组“特殊〞接口来获得操作系统核提供的特殊效劳。比方用户可以通过文件系统相关的调用请求系统翻开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置系统时间等。为了更好的保护核空间,将程序的运行空间分为核空间和用户空间,它们运行在不同的级别上,在逻辑上是相互隔离的。在Linu*中,用户程序不能直接访问核提供的效劳,必须通过系统调用来使用核提供的效劳。用户进程在通常情况下不允许访问核数据,也无法使用核函数,它们只能在用户空间操作用户数据,调用用户空间函数。Linu*中的用户编程接口〔API〕遵循了UNI*中最流行的应用编程界面标准-POSI*标准。〔这些系统调用编程接口主要是通过C库〔libc〕实现的。〕这套标准定义了一系列API。在Linu*中〔Uni*也如此〕这些API主要是通过C库〔libc〕实现的,它除了定义的一些标准的C函数外,一个很重要的任务就是提供了一套封装例程〔wrapperroutine〕将系统调用在用户空间包装后供用户编程使用。可用的文件I/O函数很多,包括:翻开文件、读文件、写文件等。大多数Linu*文件I/O只需要用到5个函数:open、read、write、lseek以及close。这5个函数是不带缓存的I/O函数,它们是POSI*标准的组成局部。在C语言中也有文件I/O函数,例如:fread、fwrite、fprintf、fscanf等。这些函数是带缓存的I/O函数,它们属于ANSIC的组成局部。Linu*下系统调用、API、系统命令、核函数的区别与联系系统调用:应用程序和核间的桥梁,是应用程序访问核的入口点;但通常情况下,应用程序通过操作系统提供的API进展编程而不是使用系统调用直接编程;linu*的全部系统调用加起来大约只有250个左右。这些系统调用按照功能逻辑大致可分为“进程控制〞、“文件系统控制〞、“系统控制〞、“存管管理〞、“网络管理〞、“socket控制〞、“用户管理〞、“进程间通信〞几类;可以使用man2syscalls命令查看系统调用的说明,或者到<核源码目录>/include/asm-i386/unistd.h源文件种找到它们的原本。1.系统调用在核里的主要用途:控制硬件;设置系统状态或读取核数据;进程管理2.什么的效劳应该存在于核,或者说什么功能应该在核而不是在用户空间;〔如效劳是否必须获得核数据;平安的角度;效率的角度等〕API:API常以C库(libc)的形式提供,C库提供了绝大局部API,每个系统调用在C库中都有对应的封装函数(通常封装函数与系统调用的名称一样)。系统调用与C库函数并不是一一对应的,有些C库函数可能使用多个系统调用来实现,也有可能多个C库函数使用同一个系统调用来实现,也有些C库函数不使用任何系统调用来实现。系统命令:系统命令是使用Linu*提供的C库函数实现的可执行程序,可用strace查看命令执行时所使用的系统调用。核函数:系统调用是用户进入核的接口,它本身不是核函数,进入核后每个系统调用会找到自己对应的核函数(即系统调用效劳例程)从用户的角度看,从底层往上看分别是:核函数,系统调用,API,系统命令核函数和系统调用的关系:核函数和普通函数很像,只不过在核中实现,因此要满足一些核编程的要求。系统调用是一层用户进入核的接口,它本身并非核函数,进入核后,不同的系统调用会找到对应到各自的核函数即,系统调用效劳例程。实际对请求效劳的是核函数而非调用接口〔系统调用〕。比方系统调用getpid实际就是调用核函数sys_getpid。Linu*下不带缓存的I/O和带缓存的I/O:概念:不带缓存的I/O:UNI*的文件I/Oread、write是不带缓存的,不带缓存是指每个read、write都调用核的一个系统调用,它们是POSI*.1的组成局部。不是核不提供缓存,而是对于用户层来说,没有提供缓存,而对核来说还是有缓存的数据:数据流->核缓存->磁盘带缓存的I/O:是指在用户层上再建立了一层缓存区〔流缓存区〕,目的是为了减少read,write等系统调用的使用次数,降低系统开销。带缓存的I/O是指标准I/O库,它由ANSIC标准说明,标准I/O库代替用户处理很多细节,比方缓存分配、以优化长度执行I/O等,提供缓存的目的是为了尽量减少read和write的调用次数;数据:数据流->流缓存区->核缓存->磁盘例如:当用fwrite函数向磁盘写数据时,先把数据写入流缓冲区中,当到达一定条件,比方流缓冲区满了,或刷新流缓冲,这时候才会把数据一次送往核提供的块缓冲,再经块缓冲写入磁盘。〔双重缓冲〕用数据流来形容两者的差异:无缓存I/O操作的数据流:数据->核缓存区->磁盘标准I/O操作的数据流:数据->流缓存区->核缓存区->磁盘文件描述符对核而言,所有翻开文件都由文件描述符应用。文件描述符是一个非负整数。当翻开一个现存文件或创立一个新文件时,核向进程返回一个文件描述符。当读、写一个文件时,用open或create返回的文件描述符标识该文件,将其作为参数传送给read或write。在windows环境下,文件描述符大体上相当于文件句柄。在POSI*.1应用程序中,整数0、1、2应被代换成符号常数:STDIN_FILENO代表标准输入〔默认是键盘〕、标准输出〔默认是屏幕〕、标准错误输出〔默认是屏幕〕,这些常数都定义在头文件<unistd.h>中。多进程编程进程是一个具有一定独立功能的程序对*个数据集合的一次运行活动。进程的实体构造:进程控制块〔PCB〕;程序段;数据段;PCB位于核的存里面的一块区域,是操作系统中最重要的记录型数据构造。PCB中记录了操作系统所需的,用于描述进程进展情况及控制进程所需的全部信息。进程块主要包括下述4方面的信息:进程描述信息处理机状态信息进程调度信息:进程状态、进程优先级〔用于描述进程使用处理机的优先级别的一个整数,优先级别高的进程先获得处理机〕、进程调度所需的其他信息〔如进程已等待CPU的时间总和、进程已执行的时间总和等〕、事件〔指进程被阻塞的原因〕。进程控制信息:程序和数据的地址〔指出该进程的程序和数据所在的存或外存地址,以便再调度到该进程执行时,能从中找到其程序和数据〕;进程同步和通信机制〔指实现进程同步和进程通信时所必须的机制,如消息队列指针、信号量等。这些数据应全部或局部存放在PCB中〕。进程的三种状态:进程的三种根本状态:〔1〕就绪状态:进程已获得除CPU外的所有必要资源,只等待CPU时的状态。一个系统会将多个处于就绪状态的进程排成一个就绪队列。〔2〕执行状态:进程已获CPU,正在执行。单处理机系统中,处于执行状态的进程只一个;多处理机系统中,有多个处于执行状态的进程。〔3〕阻塞状态:正在执行的进程由于*种原因而暂时无法继续执行,便放弃处理机而处于暂停状态,即进程执行受阻。〔这种状态又称等待状态或封锁状态〕通常导致进程阻塞的典型事件有:请求I/O,申请缓冲空间等。进程间通信进程间通信有如下一些目的:数据传输共享数据通知事件资源共享的同步进程控制多线程编程初步线程是一个程序部可以被操作系统调度并发运行的任务。在很多情况下,完成相关任务的不同代码间需要交换数据。如果采用多进程的方式,则通信就只能采用几种进程间通信的方式,但无论是信号、管道、共享存,还是信号量,它们的操作都比拟繁杂,不直观;而且大多数要使用核对象,数据要在用户空间和核空间进展切换,开销很大。但如果采用多线程方式,线程间的通信(数据交换)既直观又效率高,例如可以使用共享的全局变量。和进程相比,线程是一种“节省〞的多任务操作方式。运行于一个进程中的多个线程,它们彼此之间使用一样的地址空间,共享大局部数据,启动一个线程所花费的空间远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需的时间。〔据统计,总的来说,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别〕常用的线程函数创立线程:pthread_createintpthread_create(pthread_t*tidp,constpthread_attr_t*attr,(void*)(*start_rtn)(void*),void*arg);假设线程创立成功,则返回0。假设线程创立失败,则返回出错编号,并且*thread中的容是未定义的。返回成功时,由tidp指向的存单元被设置为新创立线程的线程ID。attr参数用于指定各种不同的线程属性。新创立的线程从start_rtn函数的地址开场运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,则需要把这些参数放到一个构造中,然后把这个构造的地址作为arg的参数传入。linu*下用C语言开发多线程程序,Linu*系统下的多线程遵循POSI*线程接口,称为pthread。参数第一个参数为指向线程标识符的指针。第二个参数用来设置线程属性。第三个参数是线程运行函数的起始地址。最后一个参数是运行函数的参数。当线程运行函数的参数不止一个时,则需要把这些参数放到一个构造中,然后将找个构造的地址当作参数传输参数。线程互斥锁的初始化pthread_mute*_initintpthread_mute*_init(pthread_mute*_t*restrictmute*,constpthread_mute*attr_t*restrictattr);pthread_mute*_tmute*=PTHREAD_MUTE*_INITIALIZER;pthread_mute*_init()函数是以动态方式创立互斥锁的,参数attr指定了新建互斥锁的属性。如果参数attr为空,则使用默认的互斥锁属性,默认属性为快速互斥锁。互斥锁的属性在创立锁的时候指定,在Linu*Threads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。3.线程初始化条件变量函数pthread_cond_init〔〕;e*ternintpthread_cond_init((pthread_cond_t*cond,constpthread_condattr_t*cond_attr));其中cond是一个指向构造pthread_cond_t的指针,cond_attr是一个指向构造pthread_condattr_t的指针。构造pthread_condattr_t是条件变量的属性构造,和互斥锁一样我们可以用它来设置条件变量是进程可用还是进程间可用,默认值是PTHREAD_PROCESS_PRIVATE,即此条件变量被同一进程的各个线程使用;如果选择为PTHREAD_PROCESS_SHARED则为多个进程间各线程公用。注意初始化条件变量只有未被使用时才能重新初始化或被释放。返回值:函数成功返回0;任何其他返回值都表示错误。释放一个条件变量的函数为pthread_cond_destroy〔pthread_cond_t*cond〕。完毕线程:pthread_e*it//线程自行完毕〔自杀〕使用pthread_e*it等待线程完毕:pthread_joinpthread_create调用成功后,新生成的线程和老线程谁先被调度执行,取决于OS,应用程序无法控制。因此,应用程序员如需等待指定线程完毕,需要使pthread_join。intpthread_join(pthread_tth,void**thread_return);th是要等待完毕的线程的标识。指针thread_return指向的位置存放的是终止线程的返回状态。sched_yield()这个函数可以使另一个级别等于或高于当前线程的线程先运行。如果没有符合条件的线程,则这个函数将会立刻返回,然后继续执行当前线程的程序。在成功完成之后返回零,否则返回-1.多线程的同步与互斥由于多个线程间极有可能回访问共享的资源〔典型的是访问同一个全局变量〕,因此多个线程间存在竞争,这就需要在多个线程间进展同步。互斥锁多线程的同步采用加锁的机制,类似于多进程间的信号量机制。在主线程中初始化锁为解锁状态〔类似于初始化0-1信号量为1〕在编译时初始化锁为解锁状态;在访问共享对象前进展加速操作〔类似于对信号量执行P操作〕;在访问共享对象后进展解锁操作〔类似于对信号量执行V操作〕;信号量互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。从本质上讲,互斥锁就是一个0-1信号量。因此当公共资源总量超过1时,互斥锁就不能用于线程同步了,此时可以采用信号量。信号量的本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。当公共资源增加时,调用sem_post()函数增加信号量。只有当信号量值大于0时,才能使用公共资源,使用后,调用函数sem_wait()减少信号量。线程属性创立线程时指定线程的属性线程的绑定轻进程:可以理解为核线程,它位于用户层和系统层之间。系统对线程资源的分配、对线程的控制是通过轻进程来实现的。一个轻进程可以控制一个或多个线程。默认情况下,启动多少轻进程,哪些轻进程来控制哪些线程是由系统来控制的,这种状况即称为非绑定的。绑定:是*个线程固定的“邦〞在一个轻进程之上。被绑定的线程具有较高的响应速度,这是因为CPU时间片的调度是面向轻进程的,绑定的线程可以保证在需要的时候总有一个轻进程可用。通过设置被绑定的轻进程的优先级和调度级可以使得绑定的线程满足诸如实时反响之类的要求。设置线程绑定状态的函数为:线程创立后改变属性一个线程如果想杀死另一个线程的话,可以通过调用pthread_cancel来完成。类似于多进程中的kill。线程调度和优先级设置线程是独立执行的。它们被分派到处理器核上,并执行分给它们的任务。每个线程均有一个调度策略和优先级,决定何时以及如何分配到处理器上。线程或线程组的调度策略可以使用这些函数通过属性对象来设置:调用形式*include<pthread.h>*include<sched.h>intpthread_attr_setinheritsched(pthread_attr_t*attr,intinheritsched);voidpthread_attr_setschedpolicy(pthread_attr_t*attr,intpolicy);intpthread_attr_setschedparam(pthread_attr_t*restrictattr,conststructsched_param*restrictparam);pthread_attr_setinheritesched()用于确定如何设置线程的调度属性,可以从创立者线程或从一个属性对象来继承调度属性。inheritsched可以为如下值:PTHREAD_INHERIT_SCHED:线程调度属性是从创立者线程继承得到,attr的任何调度属性都被忽略。PTHREAD_E*PLICIT_SCHED:线程调度属性设置为属性对象attr的调度属性。如果inheritsched值是PTHREAD_E*PLICIT_SCHED,则pthread_attr_setschedpolicy()被用于设置调度策略,而pthread_attr_setschedparam()被用于设置优先级。pthread_attr_setschedpolicy()设置线程属性对象attr的调度策略。policy的值可以为在<sched.h>头文件中定义的以下值。SCHED_FIFO:先进先出调度策略,执行线程运行到完毕。SCHED_RR:轮询调度策略,按照时

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论