- 浏览: 166750 次
- 性别:
- 来自: 南京
文章分类
- 全部博客 (327)
- JAVA (130)
- 工作笔记 (49)
- SQLSERVER (5)
- ORACLE (28)
- nginx (1)
- Unix C (16)
- 系统 (19)
- 网络技术 (17)
- WEB前端 (22)
- Eclipse (2)
- Tomcat (1)
- spring (7)
- MYSQL (12)
- Maven (6)
- JETTY (2)
- 设计 (2)
- 开源项目 (7)
- asterisk (0)
- C++ (2)
- WINDOWS (2)
- SCALA (0)
- 协议 (1)
- Netty (1)
- SHELL (1)
- mybaits (4)
- 并发 (2)
- 架构 (2)
- TCP/IP (8)
- 虚拟化 (3)
- 不要再说java慢 (0)
- mac (2)
- mysql乱码完美解决 (1)
最新评论
转自http://www.shrubbery.net/solaris9ab/SUNWdev/MTP/p37.html
Signal Handlers and Async-Signal Safety
A concept similar to thread safety is Async-Signal safety. Async-Signal-Safe operations are guaranteed not to interfere with operations that are being interrupted.
The problem of Async-Signal safety arises when the actions of a signal handler can interfere with the operation that is being interrupted.
For example, suppose a program is in the middle of a call to printf(3S) and a signal occurs whose handler itself calls printf(). In this case, the output of the two printf() statements would be intertwined. To avoid this, the handler should not call printf() itself when printf() might be interrupted by a signal.
This problem cannot be solved by using synchronization primitives because any attempted synchronization between the signal handler and the operation being synchronized would produce immediate deadlock.
Suppose that printf() is to protect itself by using a mutex. Now suppose that a thread that is in a call to printf(), and so holds the lock on the mutex, is interrupted by a signal.
If the handler (being called by the thread that is still inside of printf()) itself calls printf(), the thread that holds the lock on the mutex will attempt to take it again, resulting in an instant deadlock.
To avoid interference between the handler and the operation, either ensure that the situation never arises (perhaps by masking off signals at critical moments) or invoke only Async-Signal-Safe operations from inside signal handlers.
The only routines that POSIX guarantees to be Async-Signal-Safe are listed in Table 5-2. Any signal handler can safely call in to one of these functions.
Table 5-2 Async-Signal-Safe Functions
Interrupted Waits on Condition Variables
When an unmasked, caught signal is delivered to a thread while the thread is waiting on a condition variable, then when the signal handler returns, the thread returns from the condition wait with a spurious wakeup (one not caused by a condition signal call from another thread). In this case, the Solaris threads interfaces (cond_wait() and cond_timedwait()) return EINTR while the POSIX threads interfaces (pthread_cond_wait() and pthread_cond_timedwait()) return 0. In all cases, the associated mutex lock is reacquired before returning from the condition wait.
This does not imply that the mutex is locked while the thread is executing the signal handler. The state of the mutex in the signal handler is undefined.
The implementation of libthread in releases of Solaris prior to the Solaris 9 release guaranteed that the mutex was held while in the signal handler. Applications that rely on this old behavior will require revision for Solaris 9 and subsequent releases.
Handler cleanup is illustrated by Example 5-4.
--------------------------------------------------------------------------------
Example 5-4 Condition Variables and Interrupted Waits
int sig_catcher() {
sigset_t set;
void hdlr();
mutex_lock(&mut);
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigsetmask(SIG_UNBLOCK, &set, 0);
if (cond_wait(&cond, &mut) == EINTR) {
/* signal occurred and lock is held */
cleanup();
mutex_unlock(&mut);
return(0);
}
normal_processing();
mutex_unlock(&mut);
return(1);
}
void hdlr() {
/* state of the lock is undefined */
...
}
--------------------------------------------------------------------------------
Assume that the SIGINT signal is blocked in all threads on entry to sig_catcher() and that hdlr() has been established (with a call to sigaction(2)) as the handler for the SIGINT signal. When an unmasked and caught instance of the SIGINT signal is delivered to the thread while it is in cond_wait(), the thread calls hdlr(), then returns to the cond_wait() function where the lock on the mutex is reacquired, if necessary, and then returns EINTR from cond_wait().
Note that whether SA_RESTART has been specified as a flag to sigaction() has no effect here; cond_wait(3THR) is not a system call and is not automatically restarted. When a caught signal occurs while a thread is blocked in cond_wait(), the call always returns EINTR.
I/O Issues
One of the attractions of multithreaded programming is I/O performance. The traditional UNIX API gave you little assistance in this area--you either used the facilities of the file system or bypassed the file system entirely.
This section shows how to use threads to get more flexibility through I/O concurrency and multibuffering. This section also discusses the differences and similarities between the approaches of synchronous I/O (with threads) and asynchronous I/O (with and without threads).
I/O as a Remote Procedure Call
In the traditional UNIX model, I/O appears to be synchronous, as if you were placing a remote procedure call to the I/O device. Once the call returns, then the I/O has completed (or at least it appears to have completed--a write request, for example, might merely result in the transfer of the data to a buffer in the operating environment).
The advantage of this model is that it is easy to understand because, as a programmer you are very familiar with the concept of procedure calls.
An alternative approach not found in traditional UNIX systems is the asynchronous model, in which an I/O request merely starts an operation. The program must somehow discover when the operation completes.
This approach is not as simple as the synchronous model, but it has the advantage of allowing concurrent I/O and processing in traditional, single-threaded UNIX processes.
Tamed Asynchrony
You can get most of the benefits of asynchronous I/O by using synchronous I/O in a multithreaded program. Where, with asynchronous I/O, you would issue a request and check later to determine when it completes, you can instead have a separate thread perform the I/O synchronously. The main thread can then check (perhaps by calling pthread_join(3THR)) for the completion of the operation at some later time.
Asynchronous I/O
In most situations there is no need for asynchronous I/O, since its effects can be achieved with the use of threads, with each thread doing synchronous I/O. However, in a few situations, threads cannot achieve what asynchronous I/O can.
The most straightforward example is writing to a tape drive to make the tape drive stream. Streaming prevents the tape drive from stopping while it is being written to and moves the tape forward at high speed while supplying a constant stream of data that is written to tape.
To do this, the tape driver in the kernel must issue a queued write request when the tape driver responds to an interrupt that indicates that the previous tape-write operation has completed.
Threads cannot guarantee that asynchronous writes will be ordered because the order in which threads execute is indeterminate. Specifying the order of a write to a tape, for example, is not possible.
Asynchronous I/O Operations
#include <sys/asynch.h>
int aioread(int fildes, char *bufp, int bufs, off_t offset,
int whence, aio_result_t *resultp);
int aiowrite(int filedes, const char *bufp, int bufs,
off_t offset, int whence, aio_result_t *resultp);
aio_result_t *aiowait(const struct timeval *timeout);
int aiocancel(aio_result_t *resultp);
aioread(3AIO) and aiowrite(3AIO) are similar in form to pread(2) and pwrite(2), except for the addition of the last argument. Calls to aioread() and aiowrite() result in the initiation (or queueing) of an I/O operation.
The call returns without blocking, and the status of the call is returned in the structure pointed to by resultp. This is an item of type aio_result_t that contains the following:
int aio_return;
int aio_errno;
When a call fails immediately, the failure code can be found in aio_errno. Otherwise, this field contains AIO_INPROGRESS, meaning that the operation has been successfully queued.
You can wait for an outstanding asynchronous I/O operation to complete by calling aiowait(3AIO). This returns a pointer to the aio_result_t structure supplied with the original aioread(3AIO) or aiowrite(3) call.
This time aio_result_t contains whatever read(2) or write(2) would have returned if one of them had been called instead of the asynchronous version. If the read() or write() is successful, aio_return contains the number of bytes that were read or written; if it was not successful, aio_return is -1, and aio_errno contains the error code.
Signal Handlers and Async-Signal Safety
A concept similar to thread safety is Async-Signal safety. Async-Signal-Safe operations are guaranteed not to interfere with operations that are being interrupted.
The problem of Async-Signal safety arises when the actions of a signal handler can interfere with the operation that is being interrupted.
For example, suppose a program is in the middle of a call to printf(3S) and a signal occurs whose handler itself calls printf(). In this case, the output of the two printf() statements would be intertwined. To avoid this, the handler should not call printf() itself when printf() might be interrupted by a signal.
This problem cannot be solved by using synchronization primitives because any attempted synchronization between the signal handler and the operation being synchronized would produce immediate deadlock.
Suppose that printf() is to protect itself by using a mutex. Now suppose that a thread that is in a call to printf(), and so holds the lock on the mutex, is interrupted by a signal.
If the handler (being called by the thread that is still inside of printf()) itself calls printf(), the thread that holds the lock on the mutex will attempt to take it again, resulting in an instant deadlock.
To avoid interference between the handler and the operation, either ensure that the situation never arises (perhaps by masking off signals at critical moments) or invoke only Async-Signal-Safe operations from inside signal handlers.
The only routines that POSIX guarantees to be Async-Signal-Safe are listed in Table 5-2. Any signal handler can safely call in to one of these functions.
Table 5-2 Async-Signal-Safe Functions
_exit() |
fstat() |
read() |
sysconf() |
access() |
getegid() |
rename() |
tcdrain() |
alarm() |
geteuid() |
rmdir() |
tcflow() |
cfgetispeed() |
getgid() |
setgid() |
tcflush() |
cfgetospeed() |
getgroups() |
setpgid() |
tcgetattr() |
cfsetispeed() |
getpgrp() |
setsid() |
tcgetpgrp() |
cfsetospeed() |
getpid() |
setuid() |
tcsendbreak() |
chdir() |
getppid() |
sigaction() |
tcsetattr() |
chmod() |
getuid() |
sigaddset() |
tcsetpgrp() |
chown() |
kill() |
sigdelset() |
time() |
close() |
link() |
sigemptyset() |
times() |
creat() |
lseek() |
sigfillset() |
umask() |
dup2() |
mkdir() |
sigismember() |
uname() |
dup() |
mkfifo() |
sigpending() |
unlink() |
execle() |
open() |
sigprocmask() |
utime() |
execve() |
pathconf() |
sigsuspend() |
wait() |
fcntl() |
pause() |
sleep() |
waitpid() |
fork() |
pipe() |
stat() |
write() |
When an unmasked, caught signal is delivered to a thread while the thread is waiting on a condition variable, then when the signal handler returns, the thread returns from the condition wait with a spurious wakeup (one not caused by a condition signal call from another thread). In this case, the Solaris threads interfaces (cond_wait() and cond_timedwait()) return EINTR while the POSIX threads interfaces (pthread_cond_wait() and pthread_cond_timedwait()) return 0. In all cases, the associated mutex lock is reacquired before returning from the condition wait.
This does not imply that the mutex is locked while the thread is executing the signal handler. The state of the mutex in the signal handler is undefined.
The implementation of libthread in releases of Solaris prior to the Solaris 9 release guaranteed that the mutex was held while in the signal handler. Applications that rely on this old behavior will require revision for Solaris 9 and subsequent releases.
Handler cleanup is illustrated by Example 5-4.
--------------------------------------------------------------------------------
Example 5-4 Condition Variables and Interrupted Waits
int sig_catcher() {
sigset_t set;
void hdlr();
mutex_lock(&mut);
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigsetmask(SIG_UNBLOCK, &set, 0);
if (cond_wait(&cond, &mut) == EINTR) {
/* signal occurred and lock is held */
cleanup();
mutex_unlock(&mut);
return(0);
}
normal_processing();
mutex_unlock(&mut);
return(1);
}
void hdlr() {
/* state of the lock is undefined */
...
}
--------------------------------------------------------------------------------
Assume that the SIGINT signal is blocked in all threads on entry to sig_catcher() and that hdlr() has been established (with a call to sigaction(2)) as the handler for the SIGINT signal. When an unmasked and caught instance of the SIGINT signal is delivered to the thread while it is in cond_wait(), the thread calls hdlr(), then returns to the cond_wait() function where the lock on the mutex is reacquired, if necessary, and then returns EINTR from cond_wait().
Note that whether SA_RESTART has been specified as a flag to sigaction() has no effect here; cond_wait(3THR) is not a system call and is not automatically restarted. When a caught signal occurs while a thread is blocked in cond_wait(), the call always returns EINTR.
I/O Issues
One of the attractions of multithreaded programming is I/O performance. The traditional UNIX API gave you little assistance in this area--you either used the facilities of the file system or bypassed the file system entirely.
This section shows how to use threads to get more flexibility through I/O concurrency and multibuffering. This section also discusses the differences and similarities between the approaches of synchronous I/O (with threads) and asynchronous I/O (with and without threads).
I/O as a Remote Procedure Call
In the traditional UNIX model, I/O appears to be synchronous, as if you were placing a remote procedure call to the I/O device. Once the call returns, then the I/O has completed (or at least it appears to have completed--a write request, for example, might merely result in the transfer of the data to a buffer in the operating environment).
The advantage of this model is that it is easy to understand because, as a programmer you are very familiar with the concept of procedure calls.
An alternative approach not found in traditional UNIX systems is the asynchronous model, in which an I/O request merely starts an operation. The program must somehow discover when the operation completes.
This approach is not as simple as the synchronous model, but it has the advantage of allowing concurrent I/O and processing in traditional, single-threaded UNIX processes.
Tamed Asynchrony
You can get most of the benefits of asynchronous I/O by using synchronous I/O in a multithreaded program. Where, with asynchronous I/O, you would issue a request and check later to determine when it completes, you can instead have a separate thread perform the I/O synchronously. The main thread can then check (perhaps by calling pthread_join(3THR)) for the completion of the operation at some later time.
Asynchronous I/O
In most situations there is no need for asynchronous I/O, since its effects can be achieved with the use of threads, with each thread doing synchronous I/O. However, in a few situations, threads cannot achieve what asynchronous I/O can.
The most straightforward example is writing to a tape drive to make the tape drive stream. Streaming prevents the tape drive from stopping while it is being written to and moves the tape forward at high speed while supplying a constant stream of data that is written to tape.
To do this, the tape driver in the kernel must issue a queued write request when the tape driver responds to an interrupt that indicates that the previous tape-write operation has completed.
Threads cannot guarantee that asynchronous writes will be ordered because the order in which threads execute is indeterminate. Specifying the order of a write to a tape, for example, is not possible.
Asynchronous I/O Operations
#include <sys/asynch.h>
int aioread(int fildes, char *bufp, int bufs, off_t offset,
int whence, aio_result_t *resultp);
int aiowrite(int filedes, const char *bufp, int bufs,
off_t offset, int whence, aio_result_t *resultp);
aio_result_t *aiowait(const struct timeval *timeout);
int aiocancel(aio_result_t *resultp);
aioread(3AIO) and aiowrite(3AIO) are similar in form to pread(2) and pwrite(2), except for the addition of the last argument. Calls to aioread() and aiowrite() result in the initiation (or queueing) of an I/O operation.
The call returns without blocking, and the status of the call is returned in the structure pointed to by resultp. This is an item of type aio_result_t that contains the following:
int aio_return;
int aio_errno;
When a call fails immediately, the failure code can be found in aio_errno. Otherwise, this field contains AIO_INPROGRESS, meaning that the operation has been successfully queued.
You can wait for an outstanding asynchronous I/O operation to complete by calling aiowait(3AIO). This returns a pointer to the aio_result_t structure supplied with the original aioread(3AIO) or aiowrite(3) call.
This time aio_result_t contains whatever read(2) or write(2) would have returned if one of them had been called instead of the asynchronous version. If the read() or write() is successful, aio_return contains the number of bytes that were read or written; if it was not successful, aio_return is -1, and aio_errno contains the error code.
发表评论
-
chkconfig
2015-09-09 14:48 346Linux下chkconfig命令详解 ... -
nginx+tomcat
2015-08-01 17:12 0一、安装Tomcat和JDK 1、上传apache-tomc ... -
linux 查看系统信息
2015-08-01 17:03 0# uname -a # 查看内核/操作系统/CPU信息 ... -
常用部署命令
2015-08-01 17:00 0#gcc -v --查看版本信息 #find -name fe ... -
linux系统调整时区和时间
2015-08-01 16:55 0查看/修改Linux时区和时间 一、时区 1. 查 ... -
Linux中cp和scp命令的使用方法
2015-08-01 16:54 0Linux中cp和scp命令的使用方法 Linux为我们提 ... -
Linux 系统挂载数据盘
2015-08-01 16:49 0Linux 系统挂载数据盘 转自 http://www.23 ... -
linux 查看端口
2015-08-01 16:47 0linux端口查看命令 Linux ... -
释放内存
2015-08-01 16:45 0细心的朋友会注意到,当你在linux下频繁存取文件后,物理内存 ... -
Linux 服务器限制IP访问
2015-08-01 16:43 756转自:http://blog.163.com/yuzhongf ... -
linux系统下免费防DDOS CC攻击脚本,有效减轻服务器压力 【转】
2015-08-01 16:37 1739网站DDOS是最头疼的事。即使是国内高防的服务器,也不能100 ... -
linux下怎么查看ssh的用户登录日志
2015-08-01 16:33 498linux下登录日志在下面的目录里: cd /var/log ... -
CentOS安装iftop查看网络带宽使用情况
2015-08-01 16:28 401转自 http://mycnarms.blog.51cto.c ... -
linux查看磁盘空间
2015-08-01 16:25 461linux下空间满可能有两种情况 可以通过命令 df -h ... -
如何实现MALLOC和内存管理
2014-09-03 16:24 427如何实现MALLOC和内存管理 http://blog.cod ... -
零拷贝
2014-07-01 21:11 768Networking interface card ? ... -
C开发
2014-06-11 07:39 422FreeBSD 开发手册 http://cnsnap.cn.f ... -
Brian W. Kernighan的文章
2014-06-11 07:13 360http://www.lysator.liu.se/c/bwk ... -
df -i
2014-05-28 10:01 396查INODE使用情况. -
pthreads 教程
2013-12-26 20:21 492https://computing.llnl.gov/tuto ...
相关推荐
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,亲测可用
《Python库lambda_handlers-1.0.3-py3-none-any.whl详解》 在Python的开发环境中,库是开发者的重要工具,它们提供了丰富的功能,简化了编程过程。本文将详细探讨一个名为“lambda_handlers”的Python库,以及其在...
资源来自pypi官网。 资源全名:lambda_handlers-1.0.3-py3-none-any.whl
python库。 资源全名:fabric_am_handlers-0.12-py3-none-any.whl
《PyPI上的Python数据库处理库pydap.handlers.sql-0.1.1-py2.7.egg详解》 PyPI(Python Package Index)是Python开发者广泛使用的软件包仓库,其中包含了丰富的Python库和模块。在PyPI官网上,我们可以找到各种各样...
python库。 资源全名:pydap.handlers.netcdf-0.6.1-py2.6.egg
资源分类:Python库 所属语言:Python 资源全名:django-ohm2-handlers-light-0.1.19.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
资源分类:Python库 所属语言:Python 资源全名:pollination_handlers-0.5.0-py2.py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
官方版本,亲测可用
官方版本,亲测可用
官方版本,亲测可用
官方版本,亲测可用
官方版本,亲测可用
官方版本,亲测可用