当前位置: 首页 > news >正文

卖文具做网站好还是做电商好互联网+报名入口官网

卖文具做网站好还是做电商好,互联网+报名入口官网,seo外链工具源码,有没有免费的直播视频下载文章目录 应用程序驱动程序注册主函数注册platfrom_device注册platfrom_drive(platfrom_device 和 platfrom_drive没有注册先后之分,谁先注册都可以)platfrom_device 和 platfrom_drive 匹配成功 应用程序 应用程序比较简单,就是…

文章目录

  • 应用程序
  • 驱动程序
    • 注册主函数
    • 注册platfrom_device
    • 注册platfrom_drive(platfrom_device 和 platfrom_drive没有注册先后之分,谁先注册都可以)
    • platfrom_device 和 platfrom_drive 匹配成功

应用程序

应用程序比较简单,就是通过open来打开一个字符设备,再通过write来改变led状态

int main(int argc, char** argv)
{int fd;char status = 0;if (argc != 3){printf("Usage: %s <dev> <on|off>\n", argv[0]);printf("  eg: %s /dev/myled on\n", argv[0]);printf("  eg: %s /dev/myled off\n", argv[0]);return -1;}//openfd = open(argv[1], O_RDWR);if (fd == -1){printf("can not open %s\n", argv[1]);printf("errno=%d\n",perror);return -1;}// write//strcmp()用于比较两个字符串是否相同,一样则返回0if (strcmp(argv[2], "on") == 0){status = 1;write(fd, &status, 1);}else{status = 0;write(fd, &status, 1);}close(fd);return 0;}

驱动程序

注册主函数

当用户程序调用 open(“/dev/mydevice”, O_RDWR) 会经过这几个步骤

  1. 触发系统调用:应用程序通过 glibc 库调用 open(),进入内核态。
  2. VFS 处理请求:内核的虚拟文件系统(VFS)解析路径 /dev/mydevice,发现这是一个设备文件。
  3. 查找设备驱动:VFS 根据设备文件的主设备号(Major Number)找到对应的驱动程序。
  4. 调用驱动函数:VFS 从驱动注册的 file_operations 结构体中获取 .open 函数指针, 执行驱动实现的 mydevice_open() 函数。

所以为了让VFS能够从驱动注册的 file_operations 结构体中获取 .open 函数指针
要先

static ssize_t led_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos)
{struct inode *inode = file_inode(filp);//得到节int minor = iminor(inode);//从节点里取出次设备号char status;//在驱动程序里定义,属于内核空间int ret;//这里加个ret是因为copy_from_user函数有返回值//如果不使用返回值会有警告ret = copy_from_user(&status, buf, 1);//拷贝到val,buf:用户空间,拷贝一个字节p_ledopr -> ctrl(minor,status);//根据次设备号控制ledreturn 1;
}static int led_open(struct inode *inode, struct file *filp)
{int minor = iminor(inode);//得到次设备号printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);p_ledopr -> init(minor);//根据次设备号初始化ledreturn 0;}static struct file_operations led_fop = {.owner	 = THIS_MODULE,.open 	 = led_open,.write	 = led_write,};

系统怎么知道在哪里找这个file_operations,所以要通过register_chrdev把这个注册到内核

/*入口函数*/
//动态加载:模块可随时通过 insmod 或 modprobe 加载到运行中的内核。
static int __init led_init(void)
{int err;printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);//调用 register_chrdev 向内核注册设备,获取主设备号并绑定 file_operations。/*仅调用 register_chrdev:设备号已注册,但 /dev 下没有设备节点,应用程序无法通过 open("/dev/...") 访问设备。所以还要调用 device_create,自动生成设备节点(如 /dev/my_device0)*/major = register_chrdev(0,"jollyled",&led_fop);//内核设备号注册与操作函数绑定的入口/*内核同时提供了class_create()函数,可以用它来创建一个类,这个类存放于sys下面,创建了这个类,再调用device_create()函数来在/dev目录下创建相应的设备节点。*///class_create :/sys/class/<class_name>//device_create:/sys/class/<class_name>/<device>led_class = class_create(THIS_MODULE,"jollyled_class");err = PTR_ERR(led_class);if (IS_ERR(led_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "jollyled");return -1;}return 0;
}

有入口函数就有出口函数

/*出口函数*/
//模块可通过 rmmod 卸载,释放资源。
static void __exit led_exit(void)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);class_destroy(led_class);unregister_chrdev(major, "jollyled");//第二个参数代表设备名,但在函数的实现源码中没有用到,没有什么意义。}

出入口函数必要性:

  • 确保内核资源管理的正确性和安全性。
  • 支持模块的动态加载与卸载,提升系统灵活性。
  • 避免资源泄漏,保障内核稳定性。

注册platfrom_device

platfrom_device用于设备硬件的描述

static struct resource resources[] = {{		//引脚第几组第几个.start = GROUP_PIN(3,1),//中断类型.flags = IORESOURCE_IRQ,//设备名.name = "Jolly_led_pin",},{.start = GROUP_PIN(5,8),.flags = IORESOURCE_IRQ,.name = "Jolly_led_pin",},};static struct platform_device board_A_led_dev = {.name = "Jolly_led",//用于和platfrom_drive匹配的是这个名字.num_resources = ARRAY_SIZE(resources),.resource = resources,.dev = {.release = led_dev_release,},
};

注册进内核

//用于向内核注册一个平台设备(struct platform_device),描述设备的硬件资源(如内存地址、中断号、设备名称等)。
static int __init led_dev_init(void)
{int err;err = platform_device_register(&board_A_led_dev);   return 0;
}static void __exit led_dev_exit(void)
{platform_device_unregister(&board_A_led_dev);
}

注册platfrom_drive(platfrom_device 和 platfrom_drive没有注册先后之分,谁先注册都可以)

//函数原型const struct of_device_id *of_match_device()
static const struct of_device_id Zane_leds[] = {//of_device_id 用于device和driver的match{ .compatible = "Jolly,leddrv" },//前面的Jolly是厂商名,这个Jolly要和设备树节点zane(我自己命的名)里的compatible一致才能匹配上//后面的leddrv是模块名,注意:和driver去match的不是模块名{ },
};static struct platform_driver chip_demo_gpio_driver = {.probe      = chip_demo_gpio_probe,.remove     = chip_demo_gpio_remove,.driver     = {.name   = "Jolly_led",//没有设备树的时候通过这个name去跟platform_device的name匹配//of_device_id是一个表,把这个表的指针赋给这个of_match_table就完成了匹配表的设定:.of_match_table = Zane_leds;},
};

我的设备树节点
在这里插入图片描述

向内核注册平台驱动(struct platform_driver),提供操作设备的函数(如初始化、探测、移除等)。

static int __init chip_demo_gpio_drv_init(void)
{int err;err = platform_driver_register(&chip_demo_gpio_driver); register_led_operations(&jolly_led_demo_opr);return 0;
}static void __exit lchip_demo_gpio_drv_exit(void)
{platform_driver_unregister(&chip_demo_gpio_driver);
}

当注册了platfrom_device 或 platfrom_drive 都会去按照这个规则来匹配对方

  • platform_device的.driver_override 与 platform_driver.driver中的.name;
  • platform_device的.of_node数组的某个.name与 与 platform_driver.driver.of_match_table数组的某个.name(来源于设备树);
  • platform_device的.name 与 platform_driver.id_table数组中的某个.name;(常用)
  • platform_deivce的.name 与 platform_driver.driver中的.name;(常用)

platfrom_device 和 platfrom_drive 匹配成功

当设备的device 和其对应的driver 在总线上完成配对之后,系统就调用 platform设备的probe函数完成驱动注册最后工作。

static int chip_demo_gpio_probe(struct platform_device *pdev)
{/*platform_get_resource 跟设备树没什么关系,但设备树的节点被转换为platform_device后,设备树中的reg属性、interrupts属性也会被转换为“resource”。*///这一段不是从设备树加载设备节点/*struct resource *res;int i = 0;while (1){//通过platform_get_resource在设备树一个个匹配platform_device *pdevres = platform_get_resource(pdev, IORESOURCE_IRQ, i);if (!res)//如果是空则说明没有设备了,也就没有必要进行下面的create_device了break;g_ledpins[g_ledcnt] = res->start;//取出资源led_class_create_device(g_ledcnt);//在probe里得到一个led设备再创建一个节点i++;g_ledcnt++;}return 0;*///二进制格式dtb设备树文件需要先转化成设备节点device_node结构,然后再将device_node转换成平台设备platform_device。struct device_node *np;int err = 0;int led_pin;np = pdev->dev.of_node;//把设备树转化成设备节点device_node结构if (!np)return -1;//np:要读取的设备树节点,“pin”:要读取的属性的名字,读取到以后放到led_pinerr = of_property_read_u32(np, "pin", &led_pin);//用于读取只有一个整形值的属性g_ledpins[g_ledcnt] = led_pin;led_class_create_device(g_ledcnt);g_ledcnt++;return 0;}
http://www.dtcms.com/a/567704.html

相关文章:

  • 商丘做网站seo免费一级域名注册网站
  • 考试类网站如何做如何策划网站
  • 鄞州中学网站谁做的微网站后台内容设置
  • 企业网站黄页怎么做网络系统设计与管理
  • 长宁区科技网站建设户外俱乐部网站模板
  • 网站网页的像素尺做诚信通谁给做网站
  • 公司网站的服务费做哪个科目加强网站和公众号建设
  • 网站开发维护面试网站良精企业网站系统
  • 在国内做跨境电商怎么上外国网站如何做网站logo 设置平滑
  • 手机可以访问的网站怎么做撰写网站建设策划书范文
  • 栾城区城乡建设局网站久久建筑网平台
  • 网站搭建设计是什么任务网站的接口怎么做
  • wordpress 建站教程 下载绥化网站建设兼职
  • 潍坊网站建设价格低网站地图对seo
  • 代做宝网站医学关键词 是哪个网站做
  • 网站数据模版网站的优化策略方案
  • 湖北外贸网站建设简书 用wordpress
  • 自考在线做试卷的网站武夷山网页设计
  • 品质培训网站建设wap建站系统
  • 彩票网站代理郑州网站设计公司排名
  • 深圳做app网站的公司男科医院哪家好一些
  • 海口企业建站系统模板申请免费网站
  • 百度一下官方网站网站建设基本
  • 关于网站建设的调查问卷自己怎么做卖服装的网站
  • 南县做网站遂宁网页设计公司
  • 河源东莞网站建设怎么快速优化网站
  • 搭建网站seo汉中网站开发
  • 基于.net音乐网站开发wordpress知更鸟最新
  • wordpress建站工具包外军网站建设
  • 针对网站开发者的问答网站百度指数人群画像