デバイスドライバは、非同期の非同期I / O通知します

非同期通知を使用して能動的にユーザ・プログラム・アクセスを通知する従動、デバイスドライバになるように前記アクセスデバイスであってもよいです。アクセスを遮断することも、「休憩」非同期通知に似たかもしれないが、このように置き換え、デバイスを照会するポーリングメカニズムを必要としない、ノンブロッキングI / Oアプリケーションの使用は、アクセス可能です。アプリケーションはまた、I / O要求で発売されるとすぐに返すことができるという非同期通知に加えて。その後、クエリI / O完了、またはI / O復帰が完了した後。このプロセスは、非同期I / Oです。

アクセスをブロックし、非ブロック、ポーリング機能は、よりよい解決策デバイスのアクセスメカニズムを提供していますが、非同期通知を持っている場合、全体のメカニズムがより完全です。非同期通知を意味することである:機器の準備ができたら、ユーザプログラムに通知するためのイニシアチブをとるので、ユーザプログラムは、ハードウェアのコンセプトに「ブレーク」に非常によく似ているデバイスのステータスを照会する必要はありませんが、「信号を呼んだ方が正確であることを非同期で駆動され、 I / O」。信号は、原理的には、プロセスは、手信号プロセッサは、割込み要求が同じであると言うことができる受け取る受け取り、アナログ端末ソフトウェア機構のレベルです。信号が非同期で、信号の到着を待つために、任意のアクションを必要としない方法は、実際には、最終的にはプロセス信号が到着する何時間かわかりません。

デバイスがアクセス可能なアクセスを待った後に、非ブロックI / Oは、ユーザーがユーザーの後、プログラム自体にアクセスすることができ、クエリまたはNo機器がアクセス可能であり、そしてそれは非同期通知の通知を意味するポーリング機能手段で使用されることをI / O手段をブロックI / O処理を行います。このように、I / Oモードのこれらのタイプは、お互いを補完することができます。ブロッキング、非ブロッキングは、非同期通知自体が良いか悪いかではなく、出荷されなければならないさまざまなシナリオに応じて選択する必要があります。

利用可能なLinuxでは、クエリを百度ができる信号は、プロセス間通信(IPC)のための機構であり、信号の30種類があり、達成する非同期通知信号を使用します。2つのSIGKILL信号にSIGSYOPに加えて、プロセスが無視されるか、他のすべての信号を得ることができます。検知信号は、対応するコードは、それが処理される達したときに信号が捕捉されます。信号は、このプロセスをキャッチされていない場合は、カーネルがデフォルトの動作に対処するために取られます。

受信信号の機能

void (*singal(int signum,void(* handler))(int))(int);
//分解为
typedef void (* sighsndler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
//第一个参数是指定信号的值,第二个参数时指定针对前面信号值的处理函数,若为SIG_IGN,表示忽略给信号,若为SIG_DFL,表示使用
系统默认的方式处理信号,若为用户自定义的函数,则信号被捕获后,该函数将被执行。若signal()函数调用成功,他返回最后一次为
信号signum绑定的处理函数的handler值,失败返回SIG_ERR。

「Ctrlキー+ C」を取得し、それぞれの信号値を出力します

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void sigtem_handler(int signo)
{
    printf("Have change sig N.O %d\n",signo);
    exit(0);
}

int main()
{
    signal(SIGINT,sigtem_handler);
 //   signal(SIGTERM,sigtem_handler);
    while(1);
    return 0;
}

信号の機能に加えて、は、sigaction()関数は、プロセスの動作を変更するために使用することができるプロトタイプされた信号を、受信します。

int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
//第一个参数为信号的值,可以是除却SIGKILL及SIGSTOP外的任何一个特定有效的信号。第二个参数是指向结构体sigaction的一个实例的指针,
在结构体sigaction的实例中,指定了对特定信号的处理函数,若为空,则进程会以缺省方式对信号处理;第三个参数oldcat 指向的对象用来
保存原来对相应信号的处理函数,可指定oldact为NULL。如果把第二、第三个参数都设置为NULL,那么刚函数可以用来检测信号的有效性。

デバイスがサポート非同期通知メカニズムを作るために、ドライバは3つの作品に関わっ

  1. F_SETOWNサポートコマンドは、このプロセスにおいて制御コマンドを対応filp-> f_ownerプロセスIDを提供することができます。しかし、西郷の作品は、治療せずに、カーネル、デバイスドライバを完了しました。
  2. FASYNCフラグ変化、fasyncドライバ()関数が実行されるたびにF_SETFLサポートは、コマンドを処理します。したがって、駆動fasync()関数を実装しなければなりません。
  3. 励起信号を、対応するデバイス・リソースが利用可能で、コールkill_fasync()関数。

非同期通知デバイスドライバプログラミングは比較的簡単な、主に二つの機能およびデータ構造を使用して、データ構造は、構造fasync_structであり、二つの機能は以下のとおりです。

//处理FASYNC标志变更的函数
int fasync_helper(int fd,struct file *filp,int mode,struct fasync_struct **fa);
//释放信号用的函数
void kill_fasync(struct fasync_struct **fa,int sig,int band);

 非同期通知機能テンプレート

1.在设备结构体中添加异步结构体
struct xxx_dev{
    struct cdev cdve;
    ...
    struct fasync_struct *async_queue; //异步通知结构体
};
2.file_operations结构体中添加fasync
static struct file_operations xxx_fops{
    ...
    .fasync = xxx_fasync,
};
3.设备驱动fasync()函数模板
static int xxx_fasync(int fd,struct file *filp,int mode)
{
    struct xxx_dev *dev = filp->private_data;
    return fasync_helper(fd,filp,mode,&dev->async_queue);
} //即只需要把 异步结构体 作为fasync_helper的第四个参数返回即可
4.在write函数中添加 异步信号的读取
static ssize_t xxx_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos)
{
    struct xxx_dev *dev = filp->private_data;
    ...
    if(dev->async_queue) //产生异步读信号
        kill_fasync(&dev->async_queue,SIGIO,POLL_IN);//调用kill_fasync 释放信号
}
5.在文件关闭,即release函数中应用函数fasync将文件从异步通信列表中删除
static int xxx_release(struct inode *inode,struct file *filp)
{
    xxx_fasync(-1,filp,0);
    ...
    return 0;
}

 修正I / Oボーエン遮断するドライバコード、コンパイラのロード、テストコードを

#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>

static void signalio_handler(int signum)
{
    printf("receive a signal from mymodules,signalnum:%d\n",signum);
}

int main()
{
    int fd,oflags;
    fd = open("/dev/mymodules",O_RDWR,S_IRUSR | S_IWUSR);
    if(fd != -1){
        signal(SIGIO,signalio_handler);
        fcntl(fd,F_SETOWN,getpid());
        oflags = fcntl(fd,F_GETFL);
        fcntl(fd,F_SETFL,oflags | FASYNC);
        while(1){
            sleep(100);
        }
    }else
        printf("open device error\n");
    return 0;
}

テストをコンパイルした後、

公開された45元の記事 ウォン称賛7 ビュー10000 +

おすすめ

転載: blog.csdn.net/weixin_42005898/article/details/104818078