加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Handling of asynchronous events---reference

发布时间:2021-01-31 12:08:14 所属栏目:Linux 来源:网络整理
导读:副标题#e# http://www.win.tue.nl/~aeb/linux/lk/lk-12.html 12.?Handling of asynchronous events One wants to be notified of various events,like data that has become available,files that have changed,and signals that have been raised. FreeBSD
副标题[/!--empirenews.page--]

http://www.win.tue.nl/~aeb/linux/lk/lk-12.html

12.?Handling of asynchronous events

One wants to be notified of various events,like data that has become available,files that have changed,and signals that have been raised. FreeBSD has the nice?API. Let us discuss the Unix/Linux situation.

It is easy to wait for a single event. Usually one does a (blocking)?read(),and that is it.

Many mechanisms exist to wait for any of a set of events,or just to test whether anything interesting happened.

12.1?O_NONBLOCK

If the?open()?call that opened a file includes the O_NONBLOCK flag,the file is opened in non-blocking mode. Neither the?open()?nor any subsequent operations on the returned file descriptor will cause the calling process to wait.

A nonblocking open is useful (i) in order to obtain a file descriptor for subsequent use when no I/O is planned,e.g. for?ioctl()?calls to get or set properties of a device; especially on device files,an ordinary open might have unwanted side effects,such as a tape rewind etc. (ii) when reading from a pipe: the read will return immediately when no data is available; when writing to a pipe: the write will return immediately (without writing anything) when there are no readers.

O_NOACCESS

An obscure Linux feature is that one can open a file with the O_NOACCESS flag (defined as 3,where O_RDONLY is 0,O_WRONLY is 1 and O_RDWR is 2). In order to open a file with this mode,one needs both read and write permission. This had the same purpose: announce that no reading or writing was going to be done,and only a file descriptor for ioctl use was needed. (Used in LILO,fdformat,and a few similar utilities.)

People would love to have this facility also for directories,so that one could do a?fd = open(".",O_NOACCESS),go elsewhere,and return by?fchdir(fd). But an O_NOACCESS open fails on directories.

12.2?select

The?select()?mechanism was introduced in 4.2BSD. The prototype of this system call is

int select(int nfds,fd_set *restrict readfds,fd_set *restrict writefds,fd_set *restrict errorfds,struct timeval *restrict timeout);

It allows one to specify three sets of file descriptors (as bit masks) and a timeout. The call returns when the timeout expires or when one of the file descriptors inreadfds?has data available for reading,one of those in?writefds?has buffer space available for writing,or an error occurred for one of those in?errorfds. Upon return,the file descriptor sets and the timeout are rewritten to indicate which file descriptor has the stated condition,and how much time from the timeout is left. (Note that other Unix-type systems do not rewrite the timeout.)

There are two select system calls. The old one uses a parameter block,the new one uses five parameters. Otherwise they are equivalent.

12.3?pselect

The?pselect?system call was added in Linux 2.6.16 (and was present earlier elsewhere). With only?select()?it is difficult,almost impossible,to handle signals correctly. A signal handler itself cannot do very much: the main program is in some unknown state when the signal is delivered. The usual solution is to only raise a flag in the signal handler,and test that flag in the main program.

int gotsignal = 0;

void sighand(int x) {
gotsignal = 1;
}

int main() {
...
signal(SIGINT,sighand);
while (1) {
if (gotsignal) ...
select();
...
}

Now if one wants to wait for either a signal or some event on a file descriptor,then testing the flag and if it is not set calling?select()?has a race: maybe the signal arrived just after the flag was tested and just before select was called,and the program may hang in?select()?without reacting to the signal.

The call?pselect()?is designed to solve this problem. This function is just like?select()?but has prototype

int pselect(int nfds,const struct timespec *restrict timeout,const sigset_t *restrict sigmask);

with a sixth parameter?sigmask,and it does the equivalent of

sigset_t origmask;
sigprocmask(SIG_SETMASK,&sigmask,&origmask);
ready = select(nfds,&readfds,&writefds,&exceptfds,timeout);
sigprocmask(SIG_SETMASK,&origmask,NULL);

as an atomic action. Now one can block the signals of interest until the call of?pselect()?and have a?sigmask?that unblocks them. If a signal occurs,the call will return with?errno?set to EINTR.

This function uses a struct timespec (with nanoseconds) instead of a struct timeval (with microseconds),and does not update its value on return.

The self-pipe trick

Before the introduction of?pselect()?people resorted to obscure tricks to obtain the same effect. Famous is Daniel Bernstein's?: create a non-blocking pipe,and add a file descriptor for reading from this pipe to the?readfds?argument of?select(). In the signal handler,write a byte to the pipe. This works.

The system call

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读