BQ27501驅動和用戶空間交互數據

     內核中的數據與用戶空間數據交互常用的函數有copy_to_user,copy_from_user,和宏定義put_user,get_user,__put_user,__get_user。copy_from_user和copy_to_user函數複製塊數據,如數組,結構體;put_user,get_user,__put_user,__get_user複製的內存是簡單類型,如char,int,long,而且只能複製1,2,4,8個字節。put_user,get_user,__put_user,__get_user執行效率比copy_to_user,copy_from_user的效率要高很多。put_user和__put_user區別在於,前者會調用access_ok進行內核地址的檢查,而後者不進行地址檢查。bq27501驅動的功能是向用戶空間提供電池相關的信息;而且不需要用戶空間向電池輸入數據;另外電池的信息都是很小的數據,都可以使用unsigned short表示,所以沒有必要使用copy_to_user塊數據傳遞的函數;另外再根據《Linux驅動程序》書中“大多數驅動程序代碼中都不需要access_ok,內存管理程序會處理它”,所以選擇__put_user來向用戶空間傳遞電池信息數據。
     __put_user(var, ptr),var將內核中的數據var複製到用戶空間;ptr是用戶地址空間的指針,指向內核空間中ioctl最後一個參數。bq27501與用戶空間交互的代碼片段如下:
static long bq27501_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	BATT_INFO *pBattInfo = &BattInfo;
	unsigned short temp;
	switch(cmd)
	{
		case GET_RM:
			if((i2c_read_reg(&bq27501_i2c_client,RM_REG_ADDR_L, &pBattInfo->RemainingCapacity))>=0){
				printk(KERN_ALERT"RaminingCapacity is %u mAh ...\n",pBattInfo->RemainingCapacity);
				__put_user(pBattInfo->RemainingCapacity, (int __user *)arg);
			}
			break;
……
}
     在用戶空間, ioctl 系統調用的原型爲:int ioctl(int fd, unsigned long cmd, ...); 這個原型中的點表示函數有一個單個可選的參數, 傳統上標識爲 char *argp. 這些點在那裏只是爲了阻止在編譯時的類型檢查。第二個參數,是用戶向驅動傳遞的命令(如讀取剩餘電量值)。第三個參數的實際特點依賴所發出的特定的控制命令,即第二個參數。一些命令不用參數, 一些用一個整數值, 以及一些使用指向其他數據的指針。是否使用參數和指針是根據打開字符設備的方式決定,打開設備的方式有三種,在fcntl.h有其宏定義,只讀,只寫,讀寫,如下所示:
#define O_RDONLY	     00
#define O_WRONLY	     01
#define O_RDWR		     02
用戶空間讀取驅動中參數代碼片段如下:
if((fd = open("/dev/bq27501",2)) == -1)
	{
		perror("device open err!\n");
		return -1;
	}
	printf("open ok!\n");
	ioctl(fd,atoi(argv[1]),&v); //v是一個整型,用於保存內核空間傳遞過來的數據
	printf("(2)........cmd = [%d],val = [%d]...........\n",atoi(argv[1]),v);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章