Hello_module.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
MODULE_AUTHOR("song");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A simple test for kernel module.");
MODULE_ALIAS("a simple module");
int hello_open(struct inode *, struct file *);
int hello_release(struct inode *, struct file *);
ssize_t hello_read(struct file *, char __user *buff, size_t bufsiz, loff_t *);
ssize_t hello_write(struct file *, const char __user *buff, size_t bufsiz, loff_t *);
struct file_operations hello_fops = {
.open = hello_open,
.release = hello_release,
.read = hello_read,
.write = hello_write,
};
#define DEVICE_NAME "Hello_Driver" //proc/devices
#define BUFF_SIZE 128
int major;
unsigned char *pbuff;
int rd_pos;
int wr_pos;
static int __init hello_init(void)
{
printk(DEVICE_NAME" Hello world in kernel module\n");
major = register_chrdev(0, DEVICE_NAME, &hello_fops); //12位主設備號 20位次設備號
if(major < 0){
printk(DEVICE_NAME" register %s fial\n", DEVICE_NAME);
return major;
}
printk(DEVICE_NAME" got major number: %d\n", major);
return 0;
}
static void __exit hello_exit(void)
{
printk(DEVICE_NAME" Hello world exit\n");
unregister_chrdev(major, DEVICE_NAME); //釋放資源
}
module_init(hello_init); //模塊加載
module_exit(hello_exit); //模塊卸載
int hello_open(struct inode *pinode, struct file *pfile)
{
printk(DEVICE_NAME" hello_open\n");
wr_pos = 0;
rd_pos = 0;
pbuff = (unsigned char *)kmalloc(BUFF_SIZE, 0);
if(pbuff == NULL)
{
printk(DEVICE_NAME" kmalloc fail\n");
return 1;
}
return 0;
}
int hello_release(struct inode *pinode, struct file *pfile)
{
printk(DEVICE_NAME" hello_release\n");
kfree(pbuff);
return 0;
}
// __user *buff 用戶空間內存地址
ssize_t hello_read(struct file *pfile, char __user *buff, size_t bufsiz, loff_t *poffset)
{
int i = 0;
for(i = 0; i < bufsiz && (wr_pos - rd_pos) > 0; i++)
{
put_user(pbuff[rd_pos%BUFF_SIZE], buff + i); //複製一個字節從內核空間到用戶空間
rd_pos++;
}
#if 0
int len = wr_pos - rd_pos;
if(len > 0){
int err = copy_to_user((char *)buff, pbuff + rd_pos%BUFF_SIZE, len > bufsiz ? bufsiz : len);
rd_pos += len > bufsiz ? bufsiz : len;
if(!err)
return len > bufsiz ? bufsiz : len;
}
#endif
return i;
}
ssize_t hello_write(struct file *pfile, const char __user *buff, size_t bufsiz, loff_t *poffset)
{
int i = 0;
for(i = 0; i < bufsiz && (BUFF_SIZE - (wr_pos - rd_pos)) > 0; i++)
{
get_user(pbuff[wr_pos%BUFF_SIZE], buff + i); //複製一個字節從內核空間到用戶空間
wr_pos++;
}
return i;
#if 0
int free_len = BUFF_SIZE - (wr_pos - rd_pos);
if(free_len > bufsiz)
{
int err = copy_from_user((char *)pbuff+wr_pos%BUFF_SIZE, buff, bufsiz);
wr_pos += bufsiz;
if(!err)
return bufsiz;
}
return -1;
#endif
}
Makefile
obj-m := hello_module.o
KDIR := /home/mrhjlong/workspace/pcDuino/a20-kernel/build/sun7i_defconfig-linux
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul*
模塊處理
板子系統:
裝載:insmod hello_module.ko
卸載:rmmod hello_module
查看:lsmod
查看module信息:modinfo
查看打印信息:
tail /var/log/syslog
cat /proc/modules | grep hello
cat /proc/devices | grep Hello
查看頭文件(fs.h 結構體定義):
/home/mrhjlong/workspace/pcDuino/a20-kernel/linux-sunxi/include/linux/fs.h
創建結點(/proc/device/):mknod hello-drv c 241 0
ls -l hello-drv
test_hello_drv.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(void)
{
unsigned char buff[10] = {0};
int fd = open("/dev/hello-drv", O_RDWR);
if(fd < 0)
{
perror("open");
return 1;
}
while(1)
{
int wr = write(fd, "hello world", strlen("hello world"));
printf("write return %d \n", wr);
int rd = read(fd, buff, 64);
if(rd < 0)
perror("read");
printf("read return %d, %s\n", rd, buff);
memset(buff, 0, 64);
sleep(1);
}
close(fd);
return 0;
// unsigned int buff[10];
// int fd = open("/dev/hello-drv", O_RDWR);
// if(fd < 0)
// {
// perror("open");
// return 1;
// }
// int rd = read(fd, buff, 10);
// printf("Read return %d \n", rd);
// int wd = write(fd, buff, 10);
// if(wd < 0)
// perror("write");
// printf("write return %d\n", wd);
// close(fd);
// return 0;
}