O_ASYNC


Rev.1を表示中。最新版はこちら

FASYNCの設定は、キャラクタデバイスのファイルオペレーションの.fasyncがコールされます。ここではreadのpipeについて見てみました。

fcntlシステムコールでsetfl()が呼ばれるわけですが、そこでFASYNCの処理として.fasyncのpipe_read_fasync()がコールされます。
const struct file_operations read_pipefifo_fops = {
       .llseek         = no_llseek,
       .read           = do_sync_read,
       .aio_read       = pipe_read,
       .write          = bad_pipe_w,
       .poll           = pipe_poll,
       .unlocked_ioctl = pipe_ioctl,
       .open           = pipe_read_open,
       .release        = pipe_read_release,
       .fasync         = pipe_read_fasync,
};
pipe_read_fasync()では、inodeのかかるfasyncリストを4番目の引数として、fasync_helper()から、引数のonによって、fasyncの削除/追加の処理が行われます。
static int
pipe_read_fasync(int fd, struct file *filp, int on)
{
       struct inode *inode = filp->f_path.dentry->d_inode;
       int retval;

       mutex_lock(&inode->i_mutex);
       retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
       mutex_unlock(&inode->i_mutex);

       return retval;
}
fasync_helper()をon=1でコールすると、fasynオブジェクトの追加処理でfasync_insert_entry()がコールされます。最初のforループは同じFILEオブジェクトがすでに登録されているかチェックします。登録されているならfa->fa_fd = fdでファイルIDを更新します。(send_sigio()の引数になるのですが・・・?具体的な意味合い今ひとつです。)

登録されていないなら、fasync_strucオブジェクトを設定し、fasync_structリストに登録します。この時filp->f_flags |= FASYNCとしています。これはrelaseロックの設定で本処理がコールされるからです。new->magic = FASYNC_MAGICはメッセージ送信において、new->magicにFASYNC_MAGICが設定されていない場合、メッセージが送信されないようになっています。たぶんこの辺りの処理は今後変更されるということで、LKMのマジックナンバーの様に、カーネル毎にこのマジックナンバーが異なって、同じカーネル下(FASYNC_MAGICが同じ)で作成したモジュールでないと、FASYNCでのシグナルを送信しないようにしているのではと推測しますが・・・。
struct fasync_struct *fasync_insert_entry(int fd, struct file *filp, struct fasync_struct **fapp, struct  fasync_struct *new)
{
       struct fasync_struct *fa, **fp;

       spin_lock(&filp->f_lock);
       spin_lock(&fasync_lock);
       for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
               if (fa->fa_file != filp)
                       continue;

               spin_lock_irq(&fa->fa_lock);
               fa->fa_fd = fd;
               spin_unlock_irq(&fa->fa_lock);
               goto out;
       }

       spin_lock_init(&new->fa_lock);
       new->magic = FASYNC_MAGIC;
       new->fa_file = filp;
       new->fa_fd = fd;
       new->fa_next = *fapp;
       rcu_assign_pointer(*fapp, new);
       filp->f_flags |= FASYNC;

out:
       spin_unlock(&fasync_lock);
       spin_unlock(&filp->f_lock);
       return fa;
}
pipe_write()はパイプの書き込み処理です。データを書き込んだ後、パイプでウエイトしているタスクがあればそれを起床させ、 kill_fasync()でSIGIOを送信します。kill_fasync()はfasync_structオブジェクトリストにオブジェクトがあるかどうかチェックして、kill_fasync_rcu()で、FASYNC_MAGICが設定されているfasync_structのリスト下のプロセスに、シグナル送信を行います。

if (!(sig == SIGURG && fown->signum == 0))で、sigがソケットのSIGURGで、fown->signum(fcntlのF_SETSIG)が設定されてないと送信されないようです。
static ssize_t
pipe_write(struct kiocb *iocb, const struct iovec *_iov,
           unsigned long nr_segs, loff_t ppos)
{
       struct pipe_inode_info *pipe;
       pipe = inode->i_pipe;
  :
  :
       mutex_unlock(&inode->i_mutex);
       if (do_wakeup) {
               wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
               kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
       }
       if (ret > 0)
               file_update_time(filp);
       return ret;
}

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->fa_file->f_owner;
                       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);
       }
}


最終更新 2012/11/03 18:56:54 - north
(2012/11/03 18:56:54 作成)


検索

アクセス数
3575091
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。