Linux底層通過IOCTL方式與上層進(jìn)行交互

linux4.9通過ioctl進(jìn)行底層和上層通訊的功能,其中已實(shí)現(xiàn)應(yīng)用層通過初始化底層設(shè)備參數(shù),以及先給底層設(shè)備設(shè)置所需要讀取的內(nèi)容,再獲取設(shè)備對(duì)應(yīng)內(nèi)容產(chǎn)生的數(shù)據(jù)。


公共參數(shù)如下:

????????typedef struct {

????????????int channel_value;

????????????int adc_value;

? ? ? ? }TEST_ADC_CONFIG_READ;

????????#define TESTADC_IOC_MAGIC 'a'

????????#define IOCTL_TEST_INIT? _IO(TESTADC_IOC_MAGIC, 0)

????????#define IOCTL_TEST_SET_CHANNEL_READ_VALUE? _IO(TESTADC_IOC_MAGIC, 1)

底層部分:

? ? 1:申明一個(gè)misc設(shè)備,以及其自帶的文件操作接口

????????#define DEVICE_NAME kyan

? ? ? ? static const struct file_operations kyan_fops =

? ? ? ? {

? ? ? ? ? ? .open? ? = ms_kyan_open,

? ? ? ? ? ? .unlocked_ioctl = ms_kyan_ioctl,

? ? ? ? };

? ? ? ? static struct miscdevice kyan_miscdev = {MISC_DYNAMIC_MINOR, DEVICE_NAME, &kyan_fops};

? ? 2:通過設(shè)備注冊(cè)將misc設(shè)備注冊(cè)進(jìn)內(nèi)核,注冊(cè)成功之后會(huì)在dev目錄下新建命名為kyan的文件。

? ? ? ? misc_register(&kyan_miscdev);

? ? 3:當(dāng)?shù)讓愉N毀時(shí),將來注銷misc設(shè)備

? ? ? ? misc_deregister(&kyan_miscdev);

? ? 4:ioctl函數(shù)實(shí)現(xiàn)

????????????#define TEST_ADC_CONFIG_READ adctest //申明一個(gè)adc配置對(duì)象用于數(shù)據(jù)的設(shè)置和采集

? ? ? ????? static long ms_kyan_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

? ? ? ????? {

? ? ? ? ? ????? switch(cmd)

? ? ? ? ????? ? {

? ? ? ? ????? ? case IOCTL_TEST_INIT:

? ? ? ? ? ? ? ????? //此處可增加初始化該設(shè)備參數(shù)的功能函數(shù)

? ? ? ? ? ? ? ????? break;

? ? ? ? ????? ? case IOCTL_TEST_SET_CHANNEL_READ_VALUE:

? ? ? ? ? ? ? ????? //此處可直接操作應(yīng)用層對(duì)底層的讀和寫功能

? ? ? ? ? ? ? ????? //分別使用copy_from_user獲取用戶空間數(shù)據(jù),來進(jìn)行底層功能的設(shè)置,或者通過使用copy_to_user將來底層數(shù)據(jù)傳給用戶空間

? ? ? ? ? ? ? ????? if(copy_from_user(&adctest, (TEST_ADC_CONFIG_READ __user *)arg, sizeof(TEST_ADC_CONFIG_READ)))

? ? ? ? ? ? ? ????? {

? ? ? ? ? ? ? ????? ? ? return EFAULT;

? ? ? ? ? ? ? ????? }

? ? ? ? ? ? ? ????? channel = adctest.channel_value & 3;//由于底層chanel的值只有0、1、2、3 四種狀態(tài),所以此處可以直接與上3進(jìn)行取值。

? ? ? ? ? ? ? ????? adctest.adc_value = ms_kyan_get(channel);//此處為底層數(shù)據(jù)的實(shí)際讀取函數(shù),該函數(shù)可通過直接讀取寄存器方式進(jìn)行數(shù)據(jù)的獲取

? ? ? ? ? ? ? ????? printk("channel = %d , adc =%d \n",channel, adctest.adc_value);

? ? ? ? ? ? ? ????? if(copy_to_user((TEST_ADC_CONFIG_READ __user *)arg, &adctest, sizeof( TEST_ADC_CONFIG_READ)))

? ? ? ? ? ? ????? ? {

? ? ? ? ? ? ? ????? ? ? return EFAULT;

? ? ? ? ? ? ? ????? }

? ? ? ? ? ? ? ????? break;

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? printk("ioctl: unknown command\n");

? ? ? ? ? ? ? ? return -ENOTTY;

? ? ? ? ? ? }

? ? ? ? }

? ? 5:編譯報(bào)錯(cuò)

如果在編譯過程中報(bào)以下錯(cuò)時(shí),主要因?yàn)槲丛黾?include <linux/uaccess.h>頭文件。

應(yīng)用層部分:

1:定義采樣對(duì)象的變量,主要通過該變量與底層進(jìn)行交互

????????TEST_ADC_CONFIG_READ adctest;

2:打開dev下對(duì)應(yīng)的設(shè)備以供后續(xù)操作

????????int fd = open("/dev/kyan", O_WRONLY);

3:通過ioctl機(jī)制配置底層參數(shù)以及進(jìn)行設(shè)置和數(shù)據(jù)采集

????????ioctl(fd, IOCTL_TEST_INIT, NULL)//對(duì)底層功能進(jìn)行初始化

????????ioctl(fd, IOCTL_TEST_SET_CHANNEL_READ_VALUE, &adctest)//對(duì)底層所需要獲取的值進(jìn)行設(shè)置以及數(shù)據(jù)的讀取

4:獲取底層上報(bào)的數(shù)據(jù)

????????printf("SAR: get value %d\n", adctest.adc_value);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容