免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1816 | 回复: 0
打印 上一主题 下一主题

可重入函数(reentrant function) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-06-16 21:14 |只看该作者 |倒序浏览

由于cublog系统的缘故,将前段时间写的一篇blog文章再次贴上。
可重入函数这一概念早有接触,但一直未有系统的理解,最近阅读《APUE》信号一章时,其中讲解很到位,故总结如下。
信号作为一种软中断,能够被进程给捕获,因而也就中断进程的正常执行,转而去执行信号处理程序,最后再返回到原进程继续正常执行。然而,当进程正在执行malloc()动态内存分配时,信号产生从而转入到信号处理程序,但当信号处理程序中也用到了malloc()函数时,问题就出来了?因为malloc()通常维护一个所有已分配内存链表,当信号发生时,进程可能正在修改链表指针,这时在信号处理程序中将又一次修改链表。当然类似的情况还有不少,下文中将会谈到。

因此,在进行上层应用程序设计过程中我们就必须明确哪些函数是可重入性函数(reentrant functions)。可重入性函数通常也一定能够在信号处理程序(signal handler)中被调用。

图1 能够在信号处理程序中调用的可重入性函数(节自《APUE》)

  
  accept
  
  
  fchmod
  
  
  lseek
  
  
  sendto
  
  
  stat
  


  
  access
  
  
  fchown
  
  
  lstat
  
  
  setgid
  
  
  symlink
  


  
  aio_error
  
  
  fcntl
  
  
  mkdir
  
  
  setpgid
  
  
  sysconf
  


  
  aio_return
  
  
  fdatasync
  
  
  mkfifo
  
  
  setsid
  
  
  tcdrain
  


  
  aio_suspend
  
  
  fork
  
  
  open
  
  
  setsockopt
  
  
  tcflow
  


  
  alarm
  
  
  fpathconf
  
  
  pathconf
  
  
  setuid
  
  
  tcflush
  


  
  bind
  
  
  fstat
  
  
  pause
  
  
  shutdown
  
  
  tcgetattr
  


  
  cfgetispeed
  
  
  fsync
  
  
  pipe
  
  
  sigaction
  
  
  tcgetpgrp
  


  
  cfgetospeed
  
  
  ftruncate
  
  
  poll
  
  
  sigaddset
  
  
  tcsendbreak
  


  
  cfsetispeed
  
  
  getegid
  
  
  posix_trace_event
  
  
  sigdelset
  
  
  tcsetattr
  


  
  cfsetospeed
  
  
  geteuid
  
  
  pselect
  
  
  sigemptyset
  
  
  tcsetpgrp
  


  
  chdir
  
  
  getgid
  
  
  raise
  
  
  sigfillset
  
  
  time
  


  
  chmod
  
  
  getgroups
  
  
  read
  
  
  sigismember
  
  
  timer_getoverrun
  


  
  chown
  
  
  getpeername
  
  
  readlink
  
  
  signal
  
  
  timer_gettime
  


  
  clock_gettime
  
  
  getpgrp
  
  
  recv
  
  
  sigpause
  
  
  timer_settime
  


  
  close
  
  
  getpid
  
  
  recvfrom
  
  
  sigpending
  
  
  times
  


  
  connect
  
  
  getppid
  
  
  recvmsg
  
  
  sigprocmask
  
  
  umask
  


  
  creat
  
  
  getsockname
  
  
  rename
  
  
  sigqueue
  
  
  uname
  


  
  dup
  
  
  getsockopt
  
  
  rmdir
  
  
  sigset
  
  
  unlink
  


  
  dup2
  
  
  getuid
  
  
  select
  
  
  sigsuspend
  
  
  utime
  


  
  execle
  
  
  kill
  
  
  sem_post
  
  
  sleep
  
  
  wait
  


  
  execve
  
  
  link
  
  
  send
  
  
  socket
  
  
  waitpid
  


  
  _Exit & _exit
  
  
  listen
  
  
  sendmsg
  
  
  socketpair
  
  
  write
  


纵观上表,我们可以看出,有不少系统调用函数并没有出现,换言之也就是非可重入性函数。函数不可重入的原因主要如下:
(1)      
函数使用了static静态数据结构
如:struct passwd *getpwuid(uid_t uid);
struct passwd
*getpwnam(const char *name);
struct passwd
*getpwent(void);
以上3个函数都是返回一个指向passwd结构的指针,而该passwd结构通常都是函数中static变量,其内容在每次调用以上函数时都会被重写。因此,当进程主程序与信号处理程序中均调用了以上函数时,冲突就产生了。
(2)      
函数调用了malloc和free函数,正如文章最开始所提到的;
(3)      
函数为标准I/O的库函数,因为大多数的标准I/O库函数的实现都使用了global全局数据结构;
因此,若要写可重入性函数的做法通常是我们在函数中只修改局部变量,而不改变全局变量,或尽量不使用全局变量、静态static变量。
事实上,与可重入性函数(reentrant function)对应的还有可重入内核(reentrant kernel),其区别和联系在《深入理解Linux内核》上有较详细的讲解。

               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/27708/showart_322733.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP