#author("2019-12-26T09:19:37+09:00","default:honma","honma") #author("2021-09-24T17:14:11+09:00","default:honma","honma") * Linuxデバイスドライバ開発 カーネルスレッド [#f2f2dfaf] #seo(description,Linuxのデバイスドライバの書き方をメモ) #seo(keywords,Linux, Device Driver) ** カーネルスレッド [#vbbcfaaf] カーネルモジュールの中でkthreadを生成し、定期処理を行なうサンプル実装 #highlight(c){{ #include <linux/init.h> #include <linux/module.h> #include <linux/types.h> /* dev_t */ #include <linux/kdev_t.h> /* MKDEV(), MAJOR() */ #include <linux/fs.h> /* register_chrdev_region(), alloc_chrdev_region(), unregister_chrdev() */ #include <linux/kthread.h> /* kthread_run(), kthread_should_stop() */ MODULE_LICENSE("GPL v2"); int drv_major = 0; int drv_minor = 0; int drv_nr_devs = 1; static struct task_struct *kthread_tsk; #define SKEL_DRV_NAME "skel_drv" static long get_timestamp(void) { unsigned long ts_us = 0; struct timeval tv; do_gettimeofday(&tv); ts_us = (unsigned long long)(tv.tv_sec)*1000000 + tv.tv_usec; return ts_us; } static void my_kthread_main(void) { /* * 指定時間までCPU時間を放棄する * 単位はjiffiesなのでHZを指定することで1秒周期となる * なお、事前にstateをTASK_INTERRUPTIBLEにする必要がある */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1 * HZ); /* 起動後の処理 */ pr_info("my_kthread_main:%ld\n", get_timestamp()); } static int my_kthread(void *arg) { pr_info("%s:I %ld HZ-%d\n", __FUNCTION__, get_timestamp(), HZ); while (!kthread_should_stop()) { my_kthread_main(); } pr_info("%s:O\n", __FUNCTION__); return 0; } static int skel_init(void) { dev_t dev = 0; int ret; pr_info("%s\n", __FUNCTION__); if (drv_major) { /* 指定デバイス番号を登録する */ dev = MKDEV(drv_major, drv_minor); ret = register_chrdev_region(dev, drv_nr_devs, SKEL_DRV_NAME); } else { /* デバイス番号を動的に確保する */ ret = alloc_chrdev_region(&dev, drv_minor, drv_nr_devs, SKEL_DRV_NAME); drv_major = MAJOR(dev); } if (ret < 0) { pr_err("SKEL_DRV: cant't get major %d\n", drv_major); } else { pr_info("SKEL_DRV: char driver major number is %d\n", drv_major); } /* カーネルスレッドの起動 */ kthread_tsk = kthread_run(my_kthread, NULL, "skel kthread"); if (IS_ERR(kthread_tsk)) { pr_err("SKEL_DRV: kthread_run failed\n"); } else { pr_info("kthread_main pid:%d\n", kthread_tsk->pid); } return 0; } static void skel_exit(void) { dev_t dev = 0; pr_info("%s\n", __FUNCTION__); /* カーネルスレッドの停止 */ kthread_stop(kthread_tsk); dev = MKDEV(drv_major, drv_minor); unregister_chrdev_region(dev, drv_nr_devs); } module_init(skel_init); module_exit(skel_exit); }} #highlight(end) 実行確認 $ sudo insmod skel_drv.ko $ sudo rmmod skel_drv $ dmesg : [514702.117329] skel_init [514702.117332] SKEL_DRV: char driver major number is 243 [514702.117482] kthread_main pid:127959 [514702.117546] my_kthread:I 1548054143358956 HZ-250 [514703.117142] my_kthread_main:1548054144358638 [514704.117105] my_kthread_main:1548054145358691 [514705.117307] my_kthread_main:1548054146358977 [514706.117366] my_kthread_main:1548054147359125 [514706.425008] skel_exit [514706.425015] my_kthread_main:1548054147666807 [514706.425016] my_kthread:O #ref(skel_drv_part4.tgz,,ソースコード ダウンロード) #br #include(Linuxデバイスドライバ開発,notitle) #br #htmlinsert(amazon_book.html);