【IMX6ULLドライバ開発・学習】 16.スリープ機構_ポーリング機構_fasync非同期通知(ボタン制御LED)

スリープ ウェイクアップ メカニズム、ポーリング メカニズム、非同期通知、タイマー、タスクレット、ワーク キュー、mmap、入力サブシステムを学習したら、落ち着いてみましょう。

1. 睡眠のメカニズム

ケース: APP プログラムがキー値を読み取る - スリープ メカニズム (ブロッキングまたは非ブロッキング)
ここに画像の説明を挿入
1. キュー ヘッドの作成を待機します。

static DECLARE_WAIT_QUEUE_HEAD(key_waitqueue);

2. 待機列

wait_event_interruptible(wq, condition);

wq キューを待機しています。条件が true の場合、待機していることを意味し、その後戻ります。

3. キューを起動する

wake_up_interruptible(wq);

4. ノンブロッキングの仕組み
上記の方法はブロッキング方式ですが、ノンブロッキングにしたい場合はファイルを開くときにO_NONBLOCKフラグを付けてください。

fd = open(argv[1], O_RDWR | O_NONBLOCK);

ドライバも変更する必要があり、読み込み時にファイルのフラグがO_NONBLOCKになっているかどうかを判断する

if (!key_status && (filp->f_flags & O_NONBLOCK))  
	return -EAGAIN;  
wait_event_interruptible(key_waitqueue, key_status);

「!key_status」は、現時点で読み取るキー値がないことを示します。そのため、この時点でO_NONBLOCKフラグが設定されている場合、キューを待機してEAGAINに直接戻る必要はありません。


2. ポール機構(目覚まし時計)

ケース: APP プログラムがキー値を読み取ります - ポーリング メカニズム (非ブロッキングの場合は、直接 0 に設定できます)

ポーリングメカニズムプロセスの詳細
ここに画像の説明を挿入
コードフローチャート
ここに画像の説明を挿入


3、fasync 非同期通知

ケース: APP プログラムがキー値を読み取る - fasync 非同期通知 (推奨)
ここに画像の説明を挿入
fasync 非同期通知のコード フロー:

  1. APP プログラムはファイルを開き、シグナル関数 ( SIGIOシグナル)を定義します。
  2. fcntl関数を使用して、ファイルのフラグを設定し、プロセス PID を記録し、FASYNC/O_ASYNCフラグを設定します (これにより、ドライバー層のfasync関数の呼び出しがトリガーされます)。
  3. ドライバー層はfasync関数を実装し、fasync_helper関数を使用してfasync_struct構造体を初期化します(ファイルのフラグ ビットを保存します)。
  4. button を押した後にkill_fasync(&button_fasync, SIGIO, POLL_IN)を呼び出すと、 button_fasync->fa_fileからpidが取得されSIGIOシグナルが送信されます。
  5. アプリケーションはシグナルハンドラー関数を実行します

PS: fasync機能を無効にしたい場合はFASYNC/O_ASYNCフラグをブロックしてください。

fcntl(key_fd, F_SETFL, flags & ~O_ASYNC);

キーコードセクション:
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
アプリケーションキーコード

/* F_SETOWN: 设置将接收SIGIO和SIGURG信号的进程id */
fcntl(key_fd, F_SETOWN, getpid());

/*  F_GETFL: 取得fd的文件状态标志 */
flags = fcntl(key_fd, F_GETFL);

/* O_ASYNC: 当I/O可用的时候,允许SIGIO信号发送到进程组,
   例如:当有数据可以读的时候 */
fcntl(key_fd, F_SETFL, flags | O_ASYNC);  //启动驱动的fasync功能

ドライバー層のキーコード:

struct fasync_struct *button_fasync;

...
...

static int key_fasync (int fd, struct file *filp, int on)
{
    
    
	int retval;
	retval = fasync_helper(fd, filp, on, &button_fasync);
	if (retval < 0)
		return retval;

	return 0;
}

static struct file_operations key_ops = {
    
    
	......
	.fasync		=   key_fasync,
};

...
...

static irqreturn_t key_irq_handler(int irq, void *dev)
{
    
    
	......
	kill_fasync(&button_fasync, SIGIO, POLL_IN);
}

おすすめ

転載: blog.csdn.net/HuangChen666/article/details/131668568