将创建字符设备的三种方法记录一下,以便以后参考.
1. 使用早期的register_chardev()方法

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
int init_module(void);
void cleanup_module(void);
static int device_open(struct inode*, struct file*);
static int device_release(struct inode*, struct file*);
static ssize_t device_read(struct file*, char *, size_t, loff_t*);
static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80
static int major;
static int Device_open = 0;
static char msg[BUF_LEN];
static char *msg_ptr;
static struct file_operations fops =
{
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
};
int init_module(void)
{
major = register_chrdev(0, DEVICE_NAME, &fops);
if (major < 0)
{
printk(KERN_ALERT "Registering char device failed with %d\n", major);
return major;
}
printk(KERN_INFO "I was assigned major number %d.\n", major);
return SUCCESS;
}
void cleanup_module(void)
{
int ret = unregister_chrdev(major, DEVICE_NAME);
if (ret < 0)
{
printk(KERN_ALERT "Error in unregister chrdev %d\n", major);
}
}
static int device_open(struct inode* inode, struct file* file)
{
static int counter = 0;
if (Device_open)
{
return -EBUSY;
}
Device_open++;
sprintf(msg, "I already told you %d times hello world\nDevice_open=%d\n" ,
counter++, Device_open);
msg_ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode* inode, struct file* file)
{
Device_open--;
module_put(THIS_MODULE);
return 0;
}
static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
{
int bytes_read = 0;
if (*msg_ptr == '\0')
return 0;
printk(KERN_ALERT "length=%d\n", length);
while (length && *msg_ptr)
{
put_user(*(msg_ptr++), buffer++);
length--;
bytes_read++;
}
return bytes_read;
}
static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported\n");
return -EINVAL;
}

2. 使用cdev的方法

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/types.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
int init_module(void);
void cleanup_module(void);
static int device_open(struct inode*, struct file*);
static int device_release(struct inode*, struct file*);
static ssize_t device_read(struct file*, char *, size_t, loff_t*);
static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80

static int major;
static int Device_open = 0;
static char msg[BUF_LEN];
static char *msg_ptr;
static struct cdev *my_cdev;
static struct file_operations fops =
{
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
};
int init_module(void)
{
int err;
dev_t devid ;
alloc_chrdev_region(&devid, 0, 1, "chardev");
major = MAJOR(devid);
my_cdev = cdev_alloc();
cdev_init(my_cdev, &fops);
err = cdev_add(my_cdev, devid, 1);
if (err)
{
printk(KERN_INFO "I was assigned major number %d.\n", major);
return -1;
}
printk("major number is %d\n", MAJOR(devid));
return SUCCESS;
}
void cleanup_module(void)
{
cdev_del(my_cdev);
printk("cleanup done\n");
}
static int device_open(struct inode* inode, struct file* file)
{
static int counter = 0;
if (Device_open)
{
return -EBUSY;
}
Device_open++;
sprintf(msg, "I already told you %d times hello world\nDevice_open=%d\n",

counter++, Device_open);
msg_ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode* inode, struct file* file)
{
Device_open--;
module_put(THIS_MODULE);
return 0;
}
static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
{
int bytes_read = 0;
if (*msg_ptr == '\0')
return 0;
printk(KERN_ALERT "length=%d\n", length);
while (length && *msg_ptr)
{
put_user(*(msg_ptr++), buffer++);
length--;
bytes_read++;
}
return bytes_read;
}
static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported\n");
return -EINVAL;
}

3. 使用udev在/dev/下动态生成设备文件的方式

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/types.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/pci.h>
#include<linux/moduleparam.h>
#include<linux/init.h>
#include<linux/string.h>
#include<asm/uaccess.h>
#include<asm/unistd.h>
#include<asm/uaccess.h>
MODULE_LICENSE("GPL"); /*此处如果不加的话加载的时候会出错*/
int init_module(void);
void cleanup_module(void);
static int device_open(struct inode*, struct file*);
static int device_release(struct inode*, struct file*);
static ssize_t device_read(struct file*, char *, size_t, loff_t*);
static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
#define SUCCESS 0
#define DEVICE_NAME "chardev"
#define BUF_LEN 80

static int major;
static int Device_open = 0;
static char msg[BUF_LEN];
static char *msg_ptr;
static struct cdev *my_cdev;
static struct class *my_class;
dev_t devid ;
static struct file_operations fops =
{
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
};
int init_module(void)
{
int err;
alloc_chrdev_region(&devid, 0, 1, "chardev");
major = MAJOR(devid);
my_cdev = cdev_alloc();
cdev_init(my_cdev, &fops);
my_cdev->owner = THIS_MODULE;
err = cdev_add(my_cdev, devid, 1);
if (err)
{
printk(KERN_INFO "I was assigned major number %d.\n", major);
return -1;
}
my_class = class_create(THIS_MODULE, "chardev_class1");
if (IS_ERR(my_class))
{
printk(KERN_INFO "create class error\n");
return -1;
}
class_device_create(my_class, NULL, devid, NULL, "chardev" "%d", MINOR(devid));
printk("major number is %d\n", MAJOR(devid));
return SUCCESS;
}
void cleanup_module(void)
{
cdev_del(my_cdev);
class_device_destroy(my_class, devid);
class_destroy(my_class);
printk("cleanup done\n");
}
static int device_open(struct inode* inode, struct file* file)
{
static int counter = 0;
if (Device_open)
{
return -EBUSY;
}
Device_open++;
sprintf(msg, "I already told you %d times hello world\nDevice_open=%d\n",

counter++, Device_open);
msg_ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode* inode, struct file* file)
{
Device_open--;
module_put(THIS_MODULE);
return 0;
}
static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
{
int bytes_read = 0;
if (*msg_ptr == '\0')
return 0;
printk(KERN_ALERT "length=%d\n", length);
while (length && *msg_ptr)
{
put_user(*(msg_ptr++), buffer++);
length--;
bytes_read++;
}
return bytes_read;
}
static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported\n");
return -EINVAL;
}

创建字符设备的三种方法相关推荐

  1. eclipse创建springboot项目的三种方法

    eclipse创建springboot项目的三种方法 方法一 安装STS插件 安装插件导向窗口完成后,在eclipse右下角将会出现安装插件的进度,等插件安装完成后重启eclipse生效 新建spri ...

  2. matlab创建三维数组的三种方法

    在Matlab中习惯性的会将二维数组中的第一维称为"行"第二维称为"列",而对于三维数组的第三位则是习惯性的称为"页".在Matlab中将三 ...

  3. shell统计每一行字符数的三种方法

    shell统计每一行字符数的三种方法 $cat test.txt SlNAC2 ,SlNAC2_2 ,SlNAC2_2 ##### 方法一: $awk -F "" '{print ...

  4. Linux中创建Daemon进程的三种方法

    Linux中创建Daemon进程的三种方法 什么是daemon进程? Unix/Linux中的daemon进程类似于Windows中的后台服务进程,一直在后台运行运行,例如http服务进程nginx, ...

  5. Java 字符串匹配的三种方法

    文章目录 一.示例 二.解释 1.replace()方法 2.replaceAll()方法 3.replaceFirst()方法 4.常用的字符列表 一.示例 如图,都是为了替换字符串s中的" ...

  6. c调用python keras模型_使用TensorFlow 2.0创建Keras模型的三种方法

    TensorFlow 2.0和tf.keras提供了三种方式来实现神经网络模型:Sequential API Functional API Model subclassing 下面我将分别使用这三种方 ...

  7. 逆序输出螺旋字符矩阵(三种方法)

    第一种 **相当于从一个点慢慢遍历,每遍历一个点就设为一个负数或大数(不与)题目的数据重复就好** #include<iostream> #include<algorithm> ...

  8. Callable接口-创建线程的第三种方法

    Callable和Runable相比 //Runnable和Callable区别 //1.Callable带返回值 //2.run()不会抛异常,call()会抛异常 //3.实现的接口不同 pack ...

  9. 创建线程的第三种方法-callable futureTask

    通过实现Callable接口来创建Thread线程:其中,Callable接口(也只有一个方法)定义如下: public interface Callable<V>   { V call( ...

最新文章

  1. 控制Open With菜单项的注册表键值
  2. MacBook刷机勘错篇
  3. python的作用域分别有几种_python 作用域知识点整理
  4. python不等于缺陷
  5. python____Django实战(1)
  6. 身高预测_大部分都很准哦
  7. 五线谱上的Linux旋律
  8. 如何制作Chrome扩展?<详细教程>
  9. 简单的骨骼动画、骨骼动画理论
  10. 设置IE文档模式解决IE浏览器兼容性
  11. gpgpu_CPU与GPGPU
  12. kali中文输入法的安装
  13. 好书推荐-《策略思维》
  14. Artifact shell for APAR
  15. PNG图片转换word文档,不用下载软件,免费完成
  16. Ubuntu 如何读取U盘内容
  17. opa847方波放大电路_一种脉宽可调的高压方波发生器及高压方波发生方法
  18. ESP32温湿度 DHT11 实验
  19. pythonhiq | 计算LiH分子的哈密顿量(ongoing)
  20. python K-means聚类分析聚类数的选择-肘部法则和轮廓系数

热门文章

  1. 抖音AI火了!以视频搜视频,不知小姐姐叫什么,也能搜出她的影像
  2. 微软公布19财年财报:净利润增长22%,云计算首超个人计算业务
  3. Azure:不能把同一个certificate同时用于Azure Management和RDP
  4. java WebSocket实现一对一消息和广播消息Demo
  5. 读书笔记之MySQL技术内幕
  6. static用法解析---java语言
  7. window.postMessage实现网页间通信
  8. RR隔离级别下通过next-key locks 避免幻影读
  9. 光伏产品发展之路:从反倾销到欧盟加收税款
  10. mac mini 安装mysql数据库