#include #include #include #include #include #include #include #include #include #include #include #include #define globalmem_size 0x1000 /*全域性記憶體最大4k位元組*/
#define mem_clear 0x1 /*清0全域性記憶體*/
#define globalmem_major 0 /*預設的globalmem的主裝置號*/
static globalmem_major = globalmem_major;
/*globalmem裝置結構體*/
struct globalmem_dev
;struct globalmem_dev *globalmem_devp; /*裝置結構體指標*/
/*檔案開啟函式*/
int globalmem_open(struct inode *inode, struct file *filp)
/*檔案釋放函式*/
int globalmem_release(struct inode *inode, struct file *filp)
/* ioctl裝置控制函式 */
static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned
int cmd, unsigned long arg)
memset(dev->mem, 0, globalmem_size);
up(&dev->sem); //釋放訊號量
printk(kern_info "globalmem is set to zero\n");
break;
default:
return - einval;
} return 0;
}/*讀函式*/
static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,
loff_t *ppos)
add_wait_queue(&dev->r_wait,&wait);//進入讀等待佇列頭
//等待fifo 非空
if(dev->current_len == 0)
__set_current_state(task_interruptible);//改變程序狀態為睡眠
up($dev->sem);
schedule();//跳讀其他程序執行
if(signal_pending(current))
//如果是因為訊號喚醒
down(&dev->sem);
} /*核心空間->使用者空間*/
if (copy_to_user(buf, (void*)(dev->mem + p), count))
else
out:up(&dev->sem); //釋放訊號量
out2:remove_wait_queue(&dev->w_wait,&wait);//移除讀等待佇列頭
set_current_state(task_running);
return ret;
}/*寫函式*/
static ssize_t globalmem_write(struct file *filp, const char __user *buf,
size_t size, loff_t *ppos)
add_wait_queue(&dev->w_wait,&wait);
/*使用者空間->核心空間*/
if(dev->current_len == globalfifo_size)
__set_current_state(task_interruptible);//改變程序狀態為睡眠
up($dev->sem);
schedule();//跳讀其他程序執行
if(signal_pending(current))
//如果是因為訊號喚醒
down(&dev->sem);
}if (copy_from_user(dev->mem + p, buf, count))
ret = - efault;
else
up(&dev->sem); //釋放訊號量
return ret;
}/* seek檔案定位函式 */
static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig)
if ((unsigned int)offset > globalmem_size)
filp->f_pos = (unsigned int)offset;
ret = filp->f_pos;
break;
case 1: /*相對檔案當前位置偏移*/
if ((filp->f_pos + offset) > globalmem_size)
if ((filp->f_pos + offset) < 0)
filp->f_pos += offset;
ret = filp->f_pos;
break;
default:
ret = - einval;
break;
} return ret;
}/*檔案操作結構體*/
static const struct file_operations globalmem_fops =
;/*初始化並註冊cdev*/
static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
/*裝置驅動模組載入函式*/
int globalmem_init(void)
if (result < 0)
return result;
/* 動態申請裝置結構體的記憶體*/
globalmem_devp = kmalloc(sizeof(struct globalmem_dev), gfp_kernel);
if (!globalmem_devp) /*申請失敗*/
memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
globalmem_setup_cdev(globalmem_devp, 0);
init_mutex(&globalmem_devp->sem); /*初始化訊號量*/
init_waitqueue_head(&globalmem_devp->r_wait);
init_waitqueue_head(&globalmem_devp->w_wait);
return 0;
fail_malloc: unregister_chrdev_region(devno, 1);
return result;
}/*模組解除安裝函式*/
void globalmem_exit(void)
module_author("song baohua");
module_license("dual bsd/gpl");
module_param(globalmem_major, int, s_irugo);
module_init(globalmem_init);
module_exit(globalmem_exi
鎖:自旋鎖:適用較短等待,cpu回在此空轉
訊號量:適用較長等待,程序間,又上下文切換,消費較大
linux通常將中斷分為上半部和下半部,上半部不可打斷:應盡量減小耗時,完成中斷等級,下半部完成全部處理,很多系統也採用這種形式。
timer
第十一章
裝置驅動例項 字元裝置驅動
在整個linux裝置驅動學習中,字元裝置驅動較為基礎。通過對它的學習,對裝置驅動進一步加深了解 cdev 結構體struct cdev 講下比較重要的成員變數 dev t dev 定義了32位的裝置號,其中12位是主裝置號,20位是從裝置號。獲取主裝置號 major dev t dev 獲取從裝置號...
字元裝置驅動
字元裝置驅動 概述 塊裝置 字元裝置以及網路裝置中塊裝置和網路裝置一般都會硬體配置完備,對於程式設計師而言,能夠更多操作的就是字元裝置。設定字元裝置的一般步驟 1.初始化硬體 2.定義fops file operations 3.申請cdev,掛載fops 3.加入cdev 函式cdev add 主...
字元裝置驅動
標頭檔案包含 include 變數定義 define gpgconaddr 0x56000060 硬體中斷號定義 define key1 irq irq eint5 define key2 irq irq eint3 裝置名定義 define devname mykey 主裝置號 cdev定義 需全...