pcDuino day3

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;
}

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