宋宝华 《Linux设备驱动开发详解》示例代码之基本字符设备驱动

宋宝华《Linux设备驱动开发详解》 宋宝华《Linux设备驱动开发详解》 虚拟机以及源码。 阅读详情

最简单的字符设备驱动代码

scull.c

#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <asm/uaccess.h>

#define	SCULL_MAJOR	252
#define SCULL_NAME	"scull"
#define MAX_DATA	0x1000

static	int scull_major = SCULL_MAJOR;
struct scull_dev {
	struct cdev cdev;
	char data[MAX_DATA];
	struct semaphore sem;
};

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("BG2BKK");

struct	scull_dev *scull_devp;

int	scull_open(struct inode *inode, struct file *filp)
{
	struct scull_dev *dev = container_of(inode->i_cdev, struct scull_dev, cdev);
	filp->private_data = dev;
	printk(KERN_ALERT "open the scull device\n");
	return 0;
}

int	scull_release(struct inode *inode, struct file *filp)
{
	printk(KERN_ALERT "close the scull device\n");
	return 0;
}

ssize_t	scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops)
{
	struct scull_dev *dev = filp->private_data;
	unsigned long	p = *f_ops;
	unsigned int	cnt = count;
	int ret = 0;
	if(down_interruptible(&dev->sem))
		return -ERESTARTSYS;

	if(copy_to_user(buf, dev->data,cnt)){
		ret = -EFAULT;
	} else {
		*f_ops += cnt;
		ret = cnt;
		printk(KERN_ALERT "read %u bytes from %lu\n",cnt, p);
	}
	up(&dev->sem);
	printk(KERN_ALERT "read %d bytes\n",count);
	return ret;
}

ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)
{
	struct scull_dev *dev = filp->private_data;
	unsigned long p = *f_ops;
	unsigned int cnt = count;
	int ret = 0;
	if(down_interruptible(&dev->sem))
		return -ERESTARTSYS;

	if(copy_from_user(dev->data,buf, cnt))
		ret = -EFAULT;
	else {
		*f_ops += cnt;
		ret = cnt;
		printk(KERN_ALERT "written %u bytes from %lu\n",cnt, p);
	}
	up(&dev->sem);
	printk(KERN_ALERT "write %d bytes\n",count);
	return ret;
}

struct	file_operations scull_fops = {
	.owner	=	THIS_MODULE,
	.open	=	scull_open,
	.release=	scull_release,
	.write	=	scull_write,
	.read	=	scull_read,
};

static	void	scull_setup_cdev(struct scull_dev *dev, int index)
{
	int err, devno = MKDEV(scull_major, index);
	cdev_init(&dev->cdev, &scull_fops);
	dev->cdev.owner = THIS_MODULE;
	err = cdev_add(&dev->cdev, devno, 1);
	if(err)
		printk(KERN_NOTICE "ERROR %d adding scull_dev %d", err, index);
}

int	scull_init(void)
{
	int result;
	dev_t	devno = MKDEV(scull_major,0);
	if(scull_major)
		result = register_chrdev_region(devno, 1, "scull");
	else {
		result = alloc_chrdev_region(&devno, 0, 1, "scull");
		scull_major = MAJOR(devno);
	}
	if(result < 0)
		return result;
	
	scull_devp = kmalloc(sizeof(struct scull_dev), GFP_KERNEL);
	if(!scull_devp){
		result = -ENOMEM;
		goto fail_malloc;
	}
	memset(scull_devp, 0 , sizeof(struct scull_dev));
	scull_setup_cdev(scull_devp, 0);

	init_MUTEX(&scull_devp->sem);

	printk(KERN_ALERT "init scull device\n");
	return 0;
fail_malloc:
	unregister_chrdev_region(devno, 1);
	return result;
}

void	scull_cleanup(void)
{
	cdev_del(&scull_devp->cdev);
	kfree(scull_devp);
	unregister_chrdev_region(MKDEV(scull_major, 0), 1);
	printk(KERN_ALERT "clean scull device\n");	
}

module_init(scull_init);
module_exit(scull_cleanup);
测试代码

/*************************************************************************
 *fileName:    test.c
 *description: test the myscull.c
 *author:      Hzc
 *create time: 2007-04-20
 *modify info: -
*************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>

/* device path */
char path[] = "/dev/scull";
char buf[10];
char rbuf[10];
int i;
int t = 1;
int
main ()
{
  int f = open (path, O_RDWR);
 
  for (i = 0; i < 10; i++)
    {
      buf[i] = i;
      printf("buf[%d] = %d\n",i,buf[i]);
    }

	printf("write %d bytes\n",write (f, buf, 10));	
//  close (f);
//
//
//  f = open (path, O_RDONLY);
// if (f == -1)
//    {
//      printf ("device open error 2!\n");
//      return 1;
//    }


  printf ("Read the string from device...\n");

	printf("read %d bytes\n",read (f, rbuf, 10));	
  for (i = 0; i < 10; i++)
    {
      printf ("%d\n", rbuf[i]);
    }


  close (f);
}
Makefile

#KERNEL_DIR := /home/huang/linux-2.6.18/
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD	:= $(shell pwd)

obj-m := scull.o
default:
	$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules

test: test.c
	gcc $< -o $@.o  -g

clean:
	rm -rf *.o *.ko *~ *.order *.symvers *.markers *.mod.c


测试脚本

1  load_scull.sh

#!/bin/sh

/sbin/insmod scull.ko
mknod /dev/scull c 252 0

2  unload_scull.sh

#!/bin/sh

/sbin/rmmod scull.ko
rm /dev/scull -f

3  test.sh

#!/bin/sh
make clean
make 
make test
sudo ./unload_scull
sudo ./load_scull
sudo ./test.o


宋宝华 《Linux设备驱动开发详解》示例代码之fifo字符设备驱动 驱动代码如下: scull.c #include #include #include #include #include #include #include #include #define SCULL_MAJOR 252 #define SCULL_NAME "scull" #define MAX_DATA 0x10 static int scull_major = SC 阅读详情

相关推荐

宋宝华——Linux设备驱动开发详解:基于最新的Linux 4.0内核(第一章)

首先声明,这并不是原创,内容均来自与题目中的书本,但是文章分类并无笔记或者读书手札的选项。 为什么要读书? 答:非科班出身,看韦东山教程快速入门,但是自身了解的知识面实在是太少了,看书可能会从文字中体会到更多作者想表达的思想——并不是说韦东山教程不好,但是教程毕竟不能面面俱到,而且即使这样,看和听的过程中仍会有疏漏,自己的注意力不可能一直保持很集中。 为什么要读这本书? 答:这本书多么好吗...

qq_42067893的博客 2511

20181215《linux设备驱动开发详解》宋宝华 学习笔记(1)

1. 设备驱动的作用 设备驱动充当了硬件和应用软件的纽带(那设备驱动和操作系统之间的关系是什么?)应用软件时只需要调用系统软件的应用编程接口(API)就可让硬件去完成要求的工作。在系统没有操作系统的情况下,工程师可以根据硬件设备的特点自行定义接口,如对串口定义SerialSend()、SerialRecv(),对LED定义LightOn()、LightOff(),对Flash定义FlashWr(...

weixin_38171577的博客 4824

宋宝华的Linux驱动开发实战教程

本文还有配套的精品资源,点击获取 简介:本书由资深Linux技术专家宋宝华编写,为Linux内核驱动开发人员提供了一本全面的教程。从基础概念到高级技术,涵盖了Linux驱动开发的各个方面,包括Linux内核架构、驱动程序工作原理、各类驱动编写技巧,以及DDR内存控制器的驱动开发。书中结合实践案例和代码示例,帮助读者通过理论学习和实际操作,掌握Linux内核模块化机制及内核调...

weixin_36300623的博客 1966

Linux设备驱动开发详解笔记

设备驱动提供了硬件和应用软件之间的纽带应用软件时只需 调用系统软件的应用编程接口(API) 就可让硬件去完成要求的工作。

实力派,无需多言! 1558

Linux设备驱动开发详解 - 经典教材学习指南

I/O子系统是操作系统中负责管理输入/输出请求的关键组成部分。它作为操作系统和硬件设备之间的桥梁,使得上层的应用程序能够高效、安全地与硬件设备进行通信。I/O子系统的设计对于系统的性能和稳定性有着深远的影响。I/O子系统的主要功能包括:I/O请求的调度与管理:负责接收来自用户空间的I/O请求,将它们排队,并根据设备的当前状态和系统的调度策略进行处理。设备驱动程序的管理:I/O子系统提供了对设备驱动程序的管理机制,驱动程序是操作系统与硬件设备之间进行通信的软件接口。缓冲管理。

weixin_35973118的博客 1167

宋宝华随书源代码

宋宝华随书源代码,可以配套练习,会达到更好的效果

宋宝华linux内核驱动代码,宋宝华 《Linux设备驱动开发详解》示例代码之基本字符设备驱动...

#include #defineSCULL_MAJOR252#define SCULL_NAME"scull"#define MAX_DATA0x1000staticint scull_major = SCULL_MAJOR;struct scull_dev {struct cdev cdev;char data[MAX_DATA];struct semaphore sem;};MODULE_LI...

weixin_34828613的博客 436

《Linux设备驱动开发详解-基于最新的Linux4.0内核》源码

《Linux设备驱动开发详解-基于最新的Linux4.0内核》相关源码

Linux设备驱动开发详解

设备驱动提供了硬件和应用软件之间的纽带应用软件时只需 调用系统软件的应用编程接口(API) 就可让硬件去完成要求的工作。

实力派,无需多言! 2302

linux设备驱动源码(宋宝华)

linux设备驱动源码(宋宝华版),很全的源码

Linux设备驱动开发(宋宝华2版)代码

配套的 Linux设备驱动开发(宋宝华2版)全部代码,对于初学者很有帮助

宋宝华 《Linux设备驱动开发详解》之基本字符设备驱动misc版本

将普通字符设备驱动改造成misc设备,misc设备没有字符设备那么麻烦,以后自己写的驱动尽量用misc设备来代替 scull.c #include #include #include #include #include #include #include #include #define SCULL_NAME "scull" #define MAX_DATA 0x1000 st

bg2bkk的专栏 1661

LINUX设备驱动程序开发详解(源码)

LINUX设备驱动程序开发详解(源码),非常全,可以很好的帮你学习

第6章 字符设备驱动(宋宝华Linux设备驱动开发详解)

​ 字符设备是 3 大类设备(字符设备、块设备和网络设备)中较简单的一类设备,其驱动程序中完成的主要工作是初始化、添加和删除 cdev 结构体,申请和释放设备号,以及填充 file_operations结构体中的操作函数,实现 file_operations 结构体中的 read()、 write()和 ioctl()等函数是驱动设计的主体工作。

qq_53772633的博客 1289

[记录一个bug]av_hwdevice_ctx_create出现Cannot allocate memory(附带库运行时路径)[已解决]

新写的程序里调用ffmpeg的av_hwdevice_ctx_create()这个函数,出现Cannot allocate memory。但是另个程序一样的代码,居然是成功的。 反复检查之后无果,就跳出去查了一下,看到一个问答: Have you tried to use ffmpg executables with the same libs that you using when you run the app? Have you tried to use ffmpg executables

熊猫Ben的博客 3585

GD32F103RCT6/GD32F303RCT6(6.2)USART串口实战:从寄存器配置到DMA高效传输

本文详细介绍了GD32F103RCT6和GD32F303RCT6的USART串口通信实战,从寄存器配置到DMA高效传输的全过程。通过具体的代码示例和优化建议,帮助开发者快速掌握串口通信的关键技术,提升嵌入式开发效率。特别强调了DMA在高速数据传输中的优势和应用技巧。

weixin_33725239的博客 308

【亲测免费】 深入Linux设备驱动的世界:《Linux设备驱动详解第二版》推荐

深入Linux设备驱动的世界:《Linux设备驱动详解第二版》推荐 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在Linux开发领域,设备驱动程序是连接硬件与操作系统的桥梁,掌握设备驱动的开发技术对于嵌入式工程师和Linux开发人员来说至关重要。《Linux设备驱动详解第二版》是由资深Linux内核开发者宋宝华老师精心编写的一本全面介绍Linux设备驱动开发的权威书...

gitblog_09803的博客 1166

PostgreSQL中idle in transaction状态的5个隐藏危害及实战解决方案

本文深入剖析了PostgreSQL中`idle in transaction`连接状态的五大隐藏危害,包括内存与锁泄漏、VACUUM受阻导致表膨胀、事务ID加速消耗、连接池资源耗尽以及增加故障排查复杂度。文章提供了基于`pg_stat_activity`视图的监控方法、识别高危事务的SQL脚本,并给出了从数据库参数调优(如设置`idle_in_transaction_session_timeout`)到应用层编码规范与连接池配置的完整实战解决方案。

zzz56的博客 234

《linux设备驱动开发详解》插图汇总

该文档所有插图均来自宋宝华老师的《linux设备驱动开发详解——-基于最新的linux4.0内核》一书。截图出来仅做平时网页查阅学习。

专注嵌入式软硬件开发。 4517

12、多旋翼飞行器动力学建模与实验分析

本文探讨了多旋翼飞行器的动力学建模过程,包括使用四元数的优势、刚体运动学与动力学模型的构建,以及螺旋桨推力和扭矩对飞行性能的影响。文章还通过基础实验和分析实验研究了质量、转动惯量和螺旋桨参数对飞行状态和控制响应的影响,并结合理论分析与仿真结果总结了多旋翼飞行器的动力学特性。最后,对未来研究方向进行了展望,以提升多旋翼飞行器的性能和可靠性。

Python的专栏 207

谷歌A2A协议入门指南:附简易Python代码示例

继"关税"之后,当下最热门的词汇当属AI智能体——这种基于人工智能的软件能够执行复杂任务、实现工作流自动化并提升生产效率。但迄今为止,大多数智能体都处于各自为政的状态,难以顺畅协作。就像团队执行重大项目时,成员之间却无法交流!对于技术人员而言,一个可能遇到的典型场景是:假设你需要协调四个不同的AI服务——处理用户查询的Gemini智能体、在向量数据库进行搜索的AI应用、基于Claude的摘要生成器,以及运行专业领域逻辑的Python智能体。

独立开发,substack顶级编辑 792
上一篇: 宋宝华 《Linux设备驱动开发详解》示例代码之second设备
下一篇: 宋宝华 《Linux设备驱动开发详解》之基本字符设备驱动misc版本
bg2bkk
博客等级 码龄16年 84粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值