首页 > 系统相关 >linux 字符设备驱动

linux 字符设备驱动

时间:2023-02-08 23:22:10浏览次数:35  
标签:字符 struct int char2 dev static linux 驱动 include

这是一个简单的字符驱动程序,有open, close, read, write 功能,还有 ioctl() 功能

1. char2.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <asm/uaccess.h>

#include "driver_ioctl.h"

MODULE_LICENSE("GPL");

static char ker_buf[100];
static int  a;

static int     dev_open(struct inode* inode, struct file* filep);
static ssize_t dev_read(struct file *filep, char *buf, size_t len, loff_t *off);
static ssize_t dev_write(struct file* filep, const char *buff, size_t len, loff_t *off);
static int     dev_release(struct inode* inode, struct file* filep);
static long    my_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);

static struct file_operations fops = 
{
	.read           = dev_read,
	.write          = dev_write,
	.open           = dev_open,
	.release        = dev_release,
	.unlocked_ioctl = my_ioctl,
};


static int char2_init(void)
{
	int t = register_chrdev(91, "mydev2", &fops);
	
	if(t < 0)
	{
		printk(KERN_ALERT "2.=> DEVICE REGISTRATION FAILED.\n");
	}
	else
	{
		printk(KERN_ALERT "2.=> DEVICE REGISTERED\n");
	}

	return 0;
}


static void char2_exit(void)
{
	unregister_chrdev(91, "mydev2");
	printk(KERN_ALERT "2.=> EXITED.\n");
}

static int dev_open(struct inode* inode, struct file* filep)
{
	printk(KERN_ALERT "2.=> DEVICE OPENED\n");
	return 0;
}


static ssize_t dev_read(struct file* filep, char *buf, size_t len, loff_t *off)
{
	copy_to_user(buf, ker_buf, len);
	return len;
}

static ssize_t dev_write(struct file* filep, const char *buf, size_t len, loff_t *off)
{
	copy_from_user(ker_buf, buf, len);
	ker_buf[len] = 0;
	
	return len;
}

static int dev_release(struct inode *inode, struct file *filep)
{
	printk(KERN_ALERT "2.=> DEVICE CLOSED.\n");
	return 0;
}

static long my_ioctl(struct file* filep, unsigned int cmd, unsigned long arg)
{
	switch(cmd)
	{
		case QUERY_GET_VALUE:
			copy_to_user((int*)arg, &a, sizeof(int));
			break;
		case QUERY_SET_VALUE:
			copy_from_user(&a, (int*)arg, sizeof(int));
			break;
		case QUERY_CLEAR_VALUE:
			break;
	}
	
	return 0;
}


module_init(char2_init);
module_exit(char2_exit);

 2. driver_ioctl.h

#include <linux/ioctl.h>

#define QUERY_GET_VALUE   _IOR('q', 1, int *)
#define QUERY_CLEAR_VALUE _IO('q', 2)
#define QUERY_SET_VALUE   _IOW('q', 3, int*)

 3. Makefile

obj-m := char2.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
#	make -C /usr/src/kernels/2.6.32-431.el6.i686 M=`pwd` modules 

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

 4. test_char2.c

#include <stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <sys/ioctl.h>
#include "driver_ioctl.h"


// compile: gcc -o test_char2 test_char2.c

int main()
{
	char buf[100] = "hello";
        char rbuf[7]  = {0};
	int  a        = 10;
	int  fd;

	fd = open("/dev/mydev2", O_RDWR);

	// test read, write
	 write(fd, buf, strlen(buf));

        printf("writing into device\n");
        read(fd, rbuf, 6);
        printf("read: %s\n", rbuf);


	// test ioctl
	ioctl(fd, QUERY_SET_VALUE, &a);
	printf("value written is: %d\n", a);

	a = 0;

	printf("let's read value from device\n");
	ioctl(fd, QUERY_GET_VALUE, &a);
	
	printf("value of a is: %d\n", a);

	return 0;	
}

 5. 编译

编译 .ko:   # make
编译测试程序 test_char2.c :  # gcc -o test_char2 test_char2.c

 6. 创建字符设备文件

# mknod /dev/mydev2 c 91 1
# chmod a+w /dev/mydev2

mkdod创建设备文件, c 表示字符设备,91是主设备号, 1是次设备号
chmod为设备文件添加写权限, 否则不能向设备写数据。

 7. 测试结果:

[root@centos6 char2]# ./test_char2
writing into device
read: hello
value written is: 10
let's read value from device
value of a is: 10

 

标签:字符,struct,int,char2,dev,static,linux,驱动,include
From: https://www.cnblogs.com/bear129/p/17103689.html

相关文章

  • Jmeter-数据驱动DDT-CSV-响应断言也使用配置文件数据-且变量里有变量情况
    1、DDT数据驱动性能测试当我们使用Jmeter工具进行接口测试,可利用CSVDataSetConfig配置元件,对测试数据进行参数化,循环读取csv文档中每一行测试用例数据,来实现接口自动化......
  • Linux RAID磁盘阵列各类型优势汇总
    RAID:独立冗余磁盘阵列,将多块磁盘组合起来,组合成一个阵列,当成一个逻辑设备来使用的机制!RAID级别:仅代表磁盘组织不同,没有上下之分,组合raid时,不仅要考虑速度,还要考虑可用性......
  • linux安装oracle19c
    第一步:检查Linux系统版本1.执行命令lsb_release-a查看系统版本目前我使用的是阿里云丐版服务器,系统为CentOS7.3-x64第二步:下载Oracle19c的安装包和预安装包1.下载......
  • Linux下MySQL的配置文件(my.cnf)的存放路径
    https://blog.csdn.net/yerenyuan_pku/article/details/109919451 my.cnf是MySQL启动时加载的配置文件,一般会放在MySQL的安装目录中,用户也可以放在其他目录中进行加载。......
  • Linux 讲解DHCP服务工作原理汇总
    ​dhcp:动态主机配置协议。从bootp演变而来,引进了租约、续租功能,成为了现在的DHCP。      需要就分配,不需要就回收。 工作过程:1、当获得地址是,有租约期限,当你关机时,I......
  • linux总结:命令大全
    1.目录操作切换目录 cd查看目录 ls-l  列出文件详细信息或者直接ll-a  列出当前目录下所有文件及目录,包括隐藏的a(all)创建目录 mkdir-p   创建......
  • Linux常用命令
    防火墙IpTables设置丢弃外部所有的PING请求,也可使用REJECT拒绝请求iptables-IINPUT-picmp-jDROP根据规则号删除规则iptables-DINPUT7查看规则(号)iptables......
  • Linux vim编辑器使用方法汇总
    打开文件vim /etc/passwdvim + :打开文件时光标处于文件尾部vim +数字:打开文件时,光标定位与第几行 移动光标(编辑模式):字符移动h:向左移动l:向右移动j:向下移动k:向上......
  • linux物理机器挂载硬盘报错,can't read superblock
    场景:某宝买了个1T机械硬盘,做逻辑卷挂载时,报错误can'treadsuperblock,网上搜索过一大堆修复的问题,怎么搞都不行。自己买条黑线ATA3.0的换上即可......
  • Linux 搭建FTP服务总结
    三种解析:username-->UID :/etc/passwd   将用户名转换成UID的库。hostname--->  IP  :DNS服务,/etc/hosts  将主机名转换成IP地址servicename-->ports :......