Linux编程那些事儿_第1页
Linux编程那些事儿_第2页
Linux编程那些事儿_第3页
Linux编程那些事儿_第4页
Linux编程那些事儿_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

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

文档简介

1、Linux编程那些事儿区别return、exit、_exit、abort1、 return 是关键字,其它几个都是函数。2、 return 是函数返回,其它几个是终止进程。3、 exit(ANSI C)和_exit(POSIX)终止进程时, _exit立即进入内核,而exit会先做清理处理(如调用atexit注册的函数、关闭文件流等),再进入内核。4、 abort函数异常结束进程,不执行任何清理操作。mmap文件映射mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,那么对文件的读写操作就可以直接用指针来做而不需要read/write函数。减少了read/wr

2、ite函数中的拷贝,提高了效率。原型: void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);int munmap(void *addr, size_t len);参数解释如下:addr :/ 指定映射到本进程哪个地址处,若传入NULL,则由系统默认选择len:/映射长度prot:四种取值 PROT_EXEC表示映射的这一段可执行,例如映射共享库 PROT_READ表示映射的这一段可读 PROT_WRITE表示映射的这一段可写 PROT_NONE表示映射的这一段不可访问flag参数有很多种取

3、值,这里只讲两种, MAP_SHARED多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修改,另一个进程也会看到这种变化。 MAP_PRIVATE多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去。Fileds :/ 映射文件的fdOff:从文件的哪个点开始映射len长度。Return: map 成功则返回映射地址,反之MAP_SHAREDmunmap成功返回0,出错返回-1 Select 多路复用阻塞方式block,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函

4、数不能立即 返回。使用Select就可以完成非阻塞non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反 映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高。select能 够监视我们需要监视的文件描述符的变化情况。(一)首先说明两个结构体:1:struct fd_set一个存放文件描述符(file descriptor),即文件句柄的聚合,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(不管是Socket句柄,还是其他文件或命名管道或设备句柄)

5、建立联系,建立联系的工作由程序员完成;FD_ZERO(fd_set*fdset):清空fdset与所有文件句柄的联系。FD_SET(intfd, fd_set*fdset):建立文件句柄fd与fdset的联系。FD_CLR(intfd, fd_set*fdset):清除文件句柄fd与fdset的联系。FD_ISSET(intfd, fdset*fdset):检查fdset联系的文件句柄fd是否可读写,0表示可读写。2:struct timeval用来代表时间值,有两个成员,一个是秒数tv_sec,另一个是毫秒数tv_usec。(二)下面介绍select()函数原型:1:int select(i

6、nt maxfd1, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)maxfd1:select中监视的文件句柄数,一般设为要监视的文件中的最大文件号加一。rdfds:select()监视的可读文件句柄集合,当rdfds映象的文件句柄状态变成可读时系统告诉select函数返回。wtfds: select()监视的可写文件句柄集合,当wtfds映象的文件句柄状态变成可写时系统告诉select函数返回。exfds:select()监视的异常文件句柄集合,当exfds映象的文件句柄上有特殊情况发生时系统会告诉s

7、elect函数返回。6:timeout:select()的超时结束时间。第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,返回值: 0:可读写原子操作所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行倒结束,中间不会有任何 context switch (切换到另一个线程)。原子操作是不可分割的,在执行完毕不会被任何其它任务或事件中断。死锁的必要条件和处理所谓死

8、锁,就是指多个进程因竞争资源而形成的一种僵局,若无外力作用,这些进程都将永远不能再向前推进。A产生死锁的原因归纳为两点 (1)竞争资源 (2)进程推进顺序不当。B、产生死锁的必要条件(打破其中一个就不会死锁了)(1)互斥条件 (资源互斥访问)一个资源在一段时间内只能被一个进程所使用,具有排它性。(2)请求和保持条件一个进程在请求新资源而阻塞时,对已获得资源又保持不放。(3)不剥夺条件 进程已获得的资源,在未使用完之前不能被剥夺,只能在使用完时由自己释放。(4)环路等待条件C、处理死锁的方法由于死锁状态的出现会给整个系统带来严重的后果,所以如何解决死锁问题引起了人们的普遍关注。那么我们就得从预防

9、死锁、解除死锁等方面来处理死,具体方法比如系统设计初期即选取择一些限制条件,来破坏产生死锁的四个必要条件之一或其中几个,或者检测到死锁的话就强撤或挂起一些进程,使其暂时不要竞争资源。可重入函数描述 在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果,这就是函数的不可重入引起的,那么反过来说,什么是可重入函数呢?可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。在任何时候都可以被中断。 不可重入函数在实时系统设计中被视为不安全函数。

10、满足下列条件的函数多数是不可重入的: (1)函数体内使用了静态的数据结构; (2)函数体内调用了malloc()或者free()函数; (3)函数体内调用了标准I/O函数。 如何写出可重入的函数?1、尽量不使用全局变量。因为别的代码很可能覆盖这些变量值2、如果必须访问全局变量,记住利用互斥信号量来保护全局变量。3、和硬件交互的时候,交互前关中断,交互后开中断。4、不使用任何不可重入函数。 Pthread创建线程后必须使用join或detach释放线程资源创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有

11、一部分资源没有被回收(退出状态码),所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid) 但是调用pthread_join(pthread_id)后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码 pthread_detach(pthread_self() 或者父线程调用 pthread_detach(t

12、hread_id)(非阻塞,可立即返回) 这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。另外还有一种方式就是在创建线程的设置PTHREAD_CREATE_DETACHED属性。所以总上所述,有4种方法:1, 子线程里面调用pthread_detach(pthread_self();2, 父线程里调用pthread_detach(thread_id)3,在创建线程的设置PTHREAD_CREATE_DETACHED属性4,创建线程后用pthread_join()一直等待子线程结束。pthread_cancel pthread_exit区别pthread_exit

13、 结束线程自己,pthread_cancel结束其它线程pthread_exit()和return 的讨论在进程主函数(main())中调用pthread_exit(),只会使主函数所在的线程(可以说是进程的主线程)退出;而如果是return,编译器将使其调用进程退出的代码(如_exit()),从而导致进程及其所有线程结束运行。其次,在线程宿主函数中主动调用return,如果return语句包含在pthread_cleanup_push()/pthread_cleanup_pop()对中,则不会引起清理函数的执行,反而会导致segment fault。pthread_cleanup_push与

14、pthread_cleanup_pop比如说A、B两线程,A线程处理阻塞状态,比如阻塞在以下代码中的accept函数, pthread_mutex_lock(&mutex);sock = accept(.);/阻塞在这儿,直到有数据来pthread_mutex_unlock(&mutex);这时候线程B发现线程A等了很久了,不赖烦了,他想关掉线程A,于是B线程调用pthread_cancel()或者类似函数,请求线程A退出。当A线程收到线程B的cancel信号后,就会从accept中退出,然后终止线程,注意这个时候线程A还没有执行:pthread_mutex_unlock(&mutex);也就

15、是说锁资源没有释放,这回造成其他线程的死锁问题。所以必须在线程A接收到cancel后用一种方法来保证异常退出(也就是线程没达到终点)时可以做清理工作(主要是解锁方面),这时候,就可以使用pthread_cleanup_push和pthread_cleanup_pop了,怎么用了,把代码改成下文这样。pthread_cleanup_push(some_clean_func,.)pthread_mutex_lock(&mutex);sock = accept(.); /阻塞在这儿,直到有数据来pthread_mutex_unlock(&mutex);pthread_cleanup_pop(0);r

16、eturn 0;上面的代码,如果accept被cancel后线程退出,会自动调用some_clean_func函数,在这个函数中你可以释放锁资源。如果accept没有被cancel,那么线程继续执行,当pthread_mutex_unlock(&mutex);表示线程自己正确的释放资源了,而执行pthread_cleanup_pop(0);也就是取消掉前面的some_clean_func函数。接着return线程就正确的结束了。其实说了这么多通俗点就是:pthread_cleanup_push注册一个回调函数,如果你的线程在对应的pthread_cleanup_pop(0)之前异常退出(ret

17、urn是正常退出,其他是异常),那么系统就会执行这个回调函数(回调函数要做什么你自己决定)。但是如果在pthread_cleanup_pop之前没有异常退出,pthread_cleanup_pop(0)就把对应的回调函数取消了,而pthread_cleanup_pop(1)就不会把取消。有一点需要提的是,pthread_cleanup_push 和pthread_cleanup_pop是成对出现的。线程栈属性线程的栈是线程的私有数据,这部分内容是不共享的。在一个进程内有多个线程,这些线程都有自己的栈,但是又都要挤在进程的虚拟地址空间内。线程之间的栈内存必须保证彼此不冲突线程才能正确地运行。因此

18、,虽然大多数情况下,由系统为用户设置和线程的栈内存,但有些时候还是需要用户亲自对线程进行设置。 线程基本属性中和线程栈有关的属性有三个,分别是线程栈的大小、线程栈的最低地址和线程栈末尾警戒区的大小。 系统默认为一个新建的线程提供PAGESIZE个字节的栈空间,但是很多时候需要更改此值。有时候该线程栈可能会不够用,例如,线程体函数是一个多层递归函数,该函数的特点就是需要多层嵌套栈来保存执行过程,因此,该函数可能会造成现有的栈尺寸缩小。另一中情况刚刚相反,用户进程空间的大小是固定的。如果进程内的线程太多,那么就会造成进程的虚拟地址空间不够用,这个时候减小每一个线程的栈的大小是一个必须采取的措施。堆栈保护区堆栈保护区被用来在堆栈指针越界的情况下提供保护。如果一个线程具有堆栈保护的特性,那么系统在创建线程堆栈时会在堆栈的末尾多分配一块内存,用来防止指针访问堆栈时,溢出堆栈的边界。如果一个应用程序访问堆栈时溢出到堆栈保护区将会引发一个错误。(往往是当前线程收到一个SIGSEGV信号)提供堆栈保护区属性有两个原因:1. 首先,堆栈保护会引起系统资源浪费。如果一个应用程序创建了大量线程,而且确保这些线程不会越界访问堆栈,那么这个应用程序可以通过取消堆栈保护区来节省系统资源。2. 当线程在堆栈中存放大的数据结构时,有可能需要一个大的

温馨提示

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

评论

0/150

提交评论