================================================
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
int hello_init(void)
{
printk("hello world!\n");
return(0);
}
void hello_exit(void)
{
printk("goodbye world!\n");
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
=================================================
當 make完後....產生 ko file
insmod hello.ko
我們可以看看有甚麼變化....他會在 /proc/modules 發生變化
輸入 cat /proc/modules
就可以看到下面的訊息....
模組名 使用的記憶體 參考計數 分隔符號 活耀狀態 載入在核心的位置
hello 733 0 - Live 0x7f23_4000
然後在 /sys/module/目錄下面會增加一個hello 模組的基本資訊
輸入 tree -a /sys/module/hello
可以看到下面這些資訊
接下來繼續增加檔案....
==============#include<linux/module.h>
#include<linux/fs.h>
#include<linux/kernel.h>
#include<linux/init.h>
#define HELLO_MAJOR 234
static struct file_operations hello_fops ;
int hello_init(void)
{
int ret;
printk("hello world!\n");
ret = register_chrdev(HELLO_MAJOR, "hello1", &hello_fops);
if(ret <0){
printk("Error registering hello device\n");
return ret;}
/* Init processing here ... */
return(0);
}
void hello_exit(void)
{
printk("goodbye world!\n");
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("HELLO WORLD Example");
module_init(hello_init);
module_exit(hello_exit);
static int hello_open(struct inode * inode, struct file *file)
{
printk("hello_open : successful\n");
return 0;
}
static int hello_release(struct inode * inode, struct file *file)
{
printk("hello_release : successful\n");
return 0;
}
static int hello_read(struct file *file, char *buf, size_t count, loff_t *ptr)
{
printk("hello_read : returning zero bytes\n");
return 0;
}
static int hello_write(struct file *file,const char *buf, size_t count, loff_t *ptr)
{
printk("hello_write : accepting zero bytes\n");
return 0;
}
/*
static int hello_ioctl(struct node *inode,struct file *file, unsigned int cmd, unsigned long arg)
{
printk("hello_ioctl : cmd=%ld, arg=%ld\n",cmd,arg);
return 0;
}
*/
static struct file_operations hello_fops = {
owner : THIS_MODULE,
read : hello_read,
write : hello_write,
// ioctl : hello_ioctl,
open : hello_open,
release: hello_release
};
當進到 hello_init function時.....
我們註冊了 字元裝置
ret = register_chrdev(HELLO_MAJOR, "hello1", &hello_fops);
模組名是 hello1
然後我們把放著函式指標的結構傳進去 &hello_fops
這個函式指標會把相對應的function 連接起來....
像是在 user space 時..... 如果呼叫 open function 就會連接到 hello_open function....
寫完之後....make.....然後 sudo insmod hello.ko
然後建立一個節點
mknod /dev/hello1 c 234 0
c 代表 字元驅動程式
234 為 major number...... 0 為 sub-major number
到目前為止....已經把hello driver 掛起來變成一個檔案....
接下來就是寫一個user space 的範例...來呼叫hello driver
新增一個 main.c file..然後把下面的內容加下去
==========================================
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char ** argv)
{
int fd;
int rc =0;
char* rd_buf[16];
printf("%s : enterd\n",argv[0]);
/* open device */
fd = open("/dev/hello1",O_RDWR);
if(fd ==-1){
perror("open failed");
rc = fd;
exit(-1);
}
printf("%s : open : successful\n",argv[0]);
/* issue a read */
rc = read(fd,rd_buf,0);
if( rc == -1){
perror("read failed");
close(fd);
exit(-1);
}
printf("%s: read : returning %d bytes!\n", argv[0],rc);
close(fd);
return 0;
}
==========================================
輸入 gcc main.c
預設的輸出黨名為 a.out
sudo ./a.out
然後輸入 dmesg
就可以看到 driver 打印出來的訊息
這是因為 main.c 當中
呼叫了 open -> hello_open -> "hello_open : successful"
呼叫了 read -> hello_read -> "hello_read : returning zero bytes"
呼叫了 close -> hello_release -> "hello_release : successful"
Reference : Linux 驅動程式開發權威指南 第二版 第五章
Reference : Embedded linux 嵌入式系統開發實務 第八章