signal(SIGIO, my_handler); /* set new SIGIO handler */
fcntl(sockfd, F_SETOWN, getpid()); /* set sockfd's owner process */
oflags = fcntl(sockfd, F_GETFL); /* get old sockfd flags */
fcntl(sockfd, F_SETFL, oflags | O_ASYNC); /* set new sockfd flags */
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{
struct fd f = fdget_raw(fd);
long err = -EBADF; /* Bad file number */
if (! f.file)
goto out;
/* File is opened with O_PATH, almost nothing can be done with it */
if (unlikely(f.file->f_mode & FMODE_PATH)) {
if (! check_fcntl_cmd(cmd))
goto out1;
}
err = security_file_fcntl(f.file, cmd, arg);
if (! err)
err = do_fcntl(fd, cmd, arg, f.file); /* 实际的处理函数 */
out1:
fdput(f);
out:
return err;
}
123456789101112131415161718
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, struct fil *filp)
{
long err = -EINVAL;
switch(cmd) {
...
case F_SETFL: /* 在这里设置O_ASYNC标志 */
err = setfl(fd, filp, arg);
break;
...
case F_SETOWN: /* 在这里设置所有者进程 */
err = f_setown(filp, arg, 1);
break;
....
}
return err;
}
1234567891011121314
static int setfl(int fd, struct file *filp, unsigned long arg)
{
...
/* ->fasync() is responsible for setting the FASYNC bit. */
if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op->fasync) {
error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
if (error < 0)
goto out;
if (error > 0)
error = 0;
}
...
}
/*
* fasync_helper() is used by almost all character device drivers to set up the fasync
* queue, and for regular files by the file lease code. It returns negative on error, 0 if
* it did no changes and positive if it added / deleted the entry.
*/
int fasync_helper(int fd, struct file *filp, int on, struct fasync_struct **fapp)
{
if (! on)
return fasync_remove_entry(filp, fapp); /* 插入 */
return fasync_add_entry(fd, filp, fapp); /* 删除 */
}
int sock_wake_async(struct socket *sock, int how, int band)
{
struct socket_wq *wq;
if (! sock)
return -1;
rcu_read_lock();
wq = rcu_dereference(sock->wq); /* socket的等待队列和异步通知队列 */
if (! wq || !wq->fasync_list) { /* 如果有队列没有实例 */
rcu_read_unlock();
return -1;
}
switch(how) {
/* 检测应用程序是否通过recv()类调用来等待接收数据,如果没有才发送SIGIO信号 */
case SOCK_WAKE_WAITD:
if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
break;
goto call_kill;
/* 检测sock的发送队列是否曾经到达上限,如果有的话发送SIGIO信号 */
case SOCK_WAKE_SPACE:
if (! test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
break;
/* fall_through */
case SOCK_WAKE_IO: /* 直接发送SIGIO信号 */
call_kill:
/* 发送SIGIO信号给异步通知队列上的进程,告知IO消息 */
kill_fasync(&wq->fasync_list, SIGIO, band);
break;
case SOCK_WAKE_URG:
/* 发送SIGURG信号给异步通知队列上的进程 */
kill_fasync(&wq->fasync_list, SIGURG, band);
}
rcu_read_unlock();
return 0;
}
和设备驱动一样,最终调用kill_fasync()来发送信号给用户进程。
123456789
void kill_fasync(struct fasync_struct **fp, int sig, int band)
{
/* First a quick test without locking: usually the list is empty. */
if (*f) {
rcu_read_lock();
kill_fasync_rcu(rcu_dereference(*fp), sig, band);
rcu_read_unlock();
}
}
1234567891011121314151617181920212223242526
static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
{
while (fa) {
struct fown_struct *fown;
unsigned long flags;
if (fa->magic != FASYNC_MAGIC) {
printk(KERN_ERR "kill_fasync: bad magic number in fasync_struct!\n");
return;
}
spin_lock_irqsave(&fa->fa_lock, flags);
if (fa->fa_file) {
fown = &fa->file->f_owner; /* 持有文件的进程 */
/* Don't send SIGURG to processes which have not set a queued signum:
* SIGURG has its own default signalling mechanism. */
if (! (sig == SIGURG && fown->signum == 0))
send_sigio(fown, fa->fa_fd, band); /* 发送信号给持有文件的进程 */
}
spin_unlock_irqrestore(&fa->fa_lock, flags);
fa = rcu_dereference(fa->fa_next); /* 指向下一个异步通知结构体 */
}
}