Samsung_tiny4412(驱动笔记03)----字符设备驱动基本操作及调用流程

发布者:EtherealGrace最新更新时间:2025-01-15 来源: cnblogs关键字:Samsung  tiny4412 手机看文章 扫描二维码
随时随地手机看文章

            3. 0644    访问权限(下面文件)

    2. 加载模块时,传参方法: insmod test.ko num=1234

        num = 1234

    3. cat /sys/module/test/parameters/num

        1234


十. 字符设备:

    1. dev_t devno; ---> 设备号,设备的身份证号码 

        1. 高12位: 主设备号 

        2. 低20位: 次设备号 

    2. 设备号操作辅助宏 

        1. major = MAJOR(devno); 

        2. minor = MINOR(devno); 

        3. devno = MKDEV(major, minor); 

    3. 查看当前系统中注册的所有设备 

        cat /proc/devices 

    4. 手动创建设备节点 

        1. mknod /dev/test0 c 250 0 

        2. ls /dev/test0 -l 

            crw-r--r--  1 0  0  250,   0 Jan  1 15:31 /0 


十一. 2种字符设备注册:

    字符设备底层接口实现linux-3.5/fs/char_dev.c

    1. static inline int register_chrdev(unsigned int major, const char *name,

                                         const struct file_operations *fops)

        {

            //该函数调用了下面的3步注册方式

            return __register_chrdev(major, 0, 256, name, fops);

        }

    2. 3步详细注册:

        1. struct cdev cdev; //char device

        2. 分配设备号,有2种方式:

            1. 动态分配设备号

                int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,

            2. 静态指定设备号

                int register_chrdev_region(dev_t from, unsigned count, const char *name)

        3. 初始化cdev结构

            cdev_init();

        4. 添加cdev到系统中

            cdev_add();


十二. 驱动中常见的3种结构体:

    1. struct file_operations;      //每个驱动对应一个

    2. struct inode *inode;         //每个文件对应一个

    3. struct file *file;           //文件每打开一次,对应一个file结构维护着打开文件的相关信息

        1. loff_t       f_pos;      //文件指针

        3. unsigned int f_flags;    //文件访问标志


十三. 内核空间与用户空间之间拷贝数据:

    #include

    1. copy_to_user();

    2. copy_from_user();

    成功返回0,失败返回未完成拷贝的字节数


十四. 驱动被调用函数流程:

    1. 文件IO系统调用 ---> VFS(虚拟文件系统层) ---> 设备驱动

    2. 系统调用入口定义:arch/arm/kernel/calls.S

        1. open系统调用对应的内核入口:sys_open,该函数在VFS实现对应源文件fs/open.c;

        2. sys_open函数定义:

            SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)

        3. 关键函数调用do_sys_open();

    3. 跟踪该函数do_sys_open(),通过get_unused_fd_flags()返回一个可用的文件描述符,

        关键函数调用do_filp_open();

    4. 跟踪该函数do_filp_open(),

        关键函数调用path_openat();

    5. 跟踪该函数path_openat();

        关键函数调用do_last();

    6. 跟踪该函数do_last();

        关键函数调用nameidata_to_filp();

    7. 跟踪该函数nameidata_to_filp();

        1. 关键函数调用do_dentry_open();

        2. 关键步骤:

            //把文件inode的file_operations 保存在file结构里

            f->f_op = fops_get(inode->i_fop);


            if (!open && f->f_op)

                open = f->f_op->open;

            if (open) {

                //调用file_operations的open成员函数

                error = open(inode, f);

                if (error)

                    goto cleanup_all;

            }


        3. 那2中的inode里的i_fop是哪里来的

            1. linux-3.5/fs/inode.c

            2. 初始化inode结构的i_fop,调用init_special_inode函数:

                void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)

                {

                    inode->i_mode = mode;

                    if (S_ISCHR(mode)) {

                    //如果是字符设备,使用def_chr_fops

                        inode->i_fop = &def_chr_fops;

                        inode->i_rdev = rdev;

                    } else if (S_ISBLK(mode)) {

                        inode->i_fop = &def_blk_fops;

                        inode->i_rdev = rdev;

                    } else if (S_ISFIFO(mode))

                        inode->i_fop = &def_fifo_fops;

                    else if (S_ISSOCK(mode))

                        inode->i_fop = &bad_sock_fops;

                    else

                        printk(KERN_DEBUG 'init_special_inode: bogus i_mode (%o) for'

                                  ' inode %s:%lun', mode, inode->i_sb->s_id,

                                  inode->i_ino);

                }

            3. 如果是字符设备,使用def_chr_fops:

                const struct file_operations def_chr_fops = {

                    .open = chrdev_open,

                    .llseek = noop_llseek,

                };

            4.接下来,跟踪chrdev_open()函数

                static int chrdev_open(struct inode *inode, struct file *filp)

                {

                    struct cdev *p;

                    struct cdev *new = NULL;

                    int ret = 0;


                    spin_lock(&cdev_lock);

                    p = inode->i_cdev;

                    if (!p) {

                        struct kobject *kobj;

                        int idx;

                        spin_unlock(&cdev_lock);

                        //找到之前注册的字符设备时添加的cdev结构的kobj

                        kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);

                        if (!kobj)

                            return -ENXIO;


                        //通过container_of获取cdev结构的地址

                        new = container_of(kobj, struct cdev, kobj);

                        spin_lock(&cdev_lock);

                        /* Check i_cdev again in case somebody beat us to it while

                           we dropped the lock. */

                        p = inode->i_cdev;

                        if (!p) {

                            inode->i_cdev = p = new;

                            list_add(&inode->i_devices, &p->list);

                            new = NULL;

                        } else if (!cdev_get(p))

                            ret = -ENXIO;

[1] [2] [3]
关键字:Samsung  tiny4412 引用地址:Samsung_tiny4412(驱动笔记03)----字符设备驱动基本操作及调用流程

上一篇:Samsung_tiny4412(驱动笔记04)----volatile,container_of,file_operations,file,inode
下一篇:Samsung_tiny4412(驱动笔记01)----linux 3.5,U-Boot,Busybox,SD卡启动环境搭建

推荐阅读最新更新时间:2026-02-18 18:28

Samsung_tiny4412(驱动笔记03)----字符设备驱动基本操作及调用流程
/*********************************************************************************** * * 字符设备驱动基本操作及调用流程 * * 声明: * 1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会 * 不对齐,从而影响阅读. * 2. 以下所有的shell命令都是在root权限下运行的; *******************************************************************************
[单片机]
Samsung_tiny4412(驱动笔记10)----mdev,bus,device,driver,platform
/*********************************************************************************** * * mdev,bus,device,driver,platform * * 声明: * 1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会 * 不对齐,从而影响阅读. * 2. 由于本人水平有限,很难阐述清楚bus device driver platform的关系 * 所以强烈要求您详细参考本次提供的预热文章. * **********
[单片机]
Samsung_tiny4412(驱动笔记02)----ASM with C,MMU,Exception,GIC
/**************************************************************************** * * ASM with C,MMU,Exception,GIC * * 声明: * 1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会 * 不对齐,从而影响阅读. * 2. 以下所有的shell命令都是在root权限下运行的; * 3. 文中在需要往文件中写入内容的时候使用了如下2方式: * 1.如果文件不存在,创建文件;如果存在,以覆盖的方式往文件中添加内容: *
[单片机]
tiny4412学习笔记-将uboot、zImage、文件系统烧到emmc中
1、首先还是要将u-boot写入SD卡中从SD卡启动。 使用读卡器将SD插入电脑中,使用umount卸载u盘, fdisk -l显示其挂载点为 /dev/sdb1 切换到/home/bunfly/images/uboot_tiny4412/sd_fuse/tiny4412目录下,执行./sd_fusing.sh /dev/sdb 拨动最右边开关选择从SD卡启动。 附加编译过程:   1.进入开发板提供的源码文件包,解压uboot源码包。   cd /home/bunfly/source_code/   tar xf uboot_tiny4412-20130729.tgz   2.进入uboot文件夹,更改uboot中t
[单片机]
<font color='red'>tiny4412</font>学习<font color='red'>笔记</font>-将uboot、zImage、文件系统烧到emmc中
搭建Tiny4412的Qt交叉开发调试环境
前言 最近在学习Tiny4412下的Qt编程。第一步,首先得搭建好交叉开发调试环境。几经折腾之后,总算基本完成。兹整理一下期间的笔记,发到博客上,作为总结。也希望我入过的坑,其他人避免再入 。 另外提一点(也是事后查网才了解到的),目前业界流行Yocto/OpenEmbedded框架,很多厂商使用这个框架来构建分发开发板的BSP(包括kernel,rootfs,toolchain、gdb、库以及qt的库等),用户可以直接基于该BSP来搭建Qt交叉开发环境,从而免去自己搭建环境时所遇到的诸如依赖库缺失、toolchain版本不匹配等问题,节约了不必要的时间成本。相关案例非常多,“参考资料2~5”里列了几个例子(都未经验证,仅供参考)
[单片机]
搭建<font color='red'>Tiny4412</font>的Qt交叉开发调试环境
Tiny4412在Ubuntu下给MiniTools添加快捷方式
root@ubuntu:~/tiny4412/MiniTools-20140317# ls -l total 38008 -rw-r--r-- 1 root root 10716 Mar 29 2013 icon.png -rwxr-xr-x 1 root root 9895 Sep 12 2013 language-cn.qm -rwxr-xr-x 1 root root 37878393 Mar 17 2014 MiniTools -rwxr-xr-x 1 root root 1010312 Mar 17 2014 MiniTools_x64 -rwxr-xr-x 1 root root 292 May 15 201
[单片机]
<font color='red'>Tiny4412</font>在Ubuntu下给MiniTools添加快捷方式
tiny4412 串口驱动分析三 --- log打印的几个阶段之内核自解压
开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 u-boot:U-Boot 2010.12 Linux内核版本:linux-3.0.31 Android版本:android-4.1.2 内核自解压时期的串口打印 在zImage格式的内核启动时会自解压内核,此时打印信息如下: Uncompressing Linux... 这句话是在arch/arm/boot/compressed/misc.c中: void decompress_kernel(unsigned long output_start, unsigned lo
[单片机]
<font color='red'>tiny4412</font> 串口<font color='red'>驱动</font>分析三 --- log打印的几个阶段之内核自解压
tiny4412 串口驱动分析四 --- 修改默认的串口输出
开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 u-boot:U-Boot 2010.12 Linux内核版本:linux-3.0.31 Android版本:android-4.1.2 tiny4412默认是从uart0来输出和读取信息的,而tiny4412上留了两个串口,分别对应的是uart0和uart3,下面我们修改配置,使控制终端从uart0变成uart3 修改u-boot配置 在前面分析u-boot串口驱动的时候发现,在tiny4412.h中定义了 #define CONFIG_SERIAL0 1 然后再初始化串口的时候会根据这个
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved