❶ 能提问题一下uvent是什么么
1. Uevent的功能
Uevent是Kobject的一部分,用于在Kobject状态发生改变时,例如增加、移除等,通知用户空间程序。用户空间程序收到这样的事件后,会做相应的处理。
该机制通常是用来支持热拔插设备的,例如U盘插入后,USB相关的驱动软件会动态创建用于表示该U盘的device结构(相应的也包括其中的kobject),并告知用户空间程序,为该U盘动态的创建/dev/目录下的设备节点,更进一步,可以通知其它的应用程序,将该U盘设备mount到系统中,从而动态的支持该设备。
2. Uevent在kernel中的位置
Uevent的机制是比较简单的,设备模型中任何设备有事件需要上报时,会触发Uevent提供的接口。Uevent模块准备好上报事件的格式后,可以通过两个途径把事件上报到用户空间:一种是通过kmod模块,直接调用用户空间的可执行文件;另一种是通过netlink通信机制,将事件从内核空间传递给用户空间。
3. Uevent的内部逻辑解析
3.1 Source Code位置
Uevent的代码比较简单,主要涉及kobject.h和kobject_uevent.c两个文件,如下:
include/linux/kobject.h
lib/kobject_uevent.c
3.2 数据结构描述
kobject.h定义了uevent相关的常量和数据结构
kobject_action定义了event的类型
4.uevent是sysfs向用户空间发出的消息。
5.uevent用户空间部分
uevent的用户空间程序有两个,一个是udev,一个是mdev。 udev通过netlink监听uevent消息,它能完成两个功能: 自动加载模块 ;根据uevent消息在dev目录下添加、删除设备节点。
另一个是mdev,mdev在busybox的代码包中能找到,它通过上节提到的uevent_helper函数被调用。
6.其他
kobject代表sysfs中的目录。
ktype代表kobject的类型,主要包含release函数和attr的读写函数。
kset包含了subsystem概念,kset本身也是一个kobject,所以里面包含了一个kobject对象。另外,kset中包含kset_uevent_ops,里面主要定义了三个函数
int (*filter)(struct kset *kset, struct kobject *kobj); const char *(*name)(struct kset *kset, struct kobject *kobj);
int (*uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env
*env);
这三个函数都与uevent相关。filter用于判断uevent是否要发出去。name用于得到subsystem的名字。uevent用于填充env变量。
❷ 如何使linux内核2.6.31支持yaffs2文件系统
下面操作的前提是:内核支持nand flash
一. 下载yaffs2源码,(我将源码反正/opt目录下),并解压源码,进入源码目录
# tar xzvf yaffs2.tar.gz
# cd yaffs2
二. 为内核添加yaffs2文件系统补丁,执行:
# ./patch-ker.sh c m /..../linux-2.6.31.1 <----c m后面接的是内核源码所在的目录
执行完后,在内核源码fs目录下就多了一个yaffs2目录,同时Makefile和Kconfig文件也增加了对yaffs2的配置和编译条件。
三. 配置内核对yaffs2的支持
这里的配置根据自己的需求,把不用的文件系统都去掉。
#make menuconfig
找到下面的配置:
File systems --->
DOS/FAT/NT Filesystems --->
<*> MSDOS fs support
<*> VFAT (Windows95) fs support
Miscellaneous filesystems --->
<*> YAFFS2 file system support
[*] Autoselect yaffs2 format
配置语言选项:
Native Language support --->
(iso8859-1) Default NLS Option
<*> Codepage 437(United States, Canada)
<*> Simplified Chinese charset(CP936, GB2312)
<*> NLS ISO8859-1 (Latin 1; Western European Language)
<*> NLS UTF-8
现在内核已经支持NandFlash和yaffs2文件系统,重新编译内核:
#make zImage
将编译好的内核烧入NandFlash后,再烧入yaffs2文件系统,就可以了。
四. 制作yaffs2根文件系统
1. 环境
(1) 交叉编译器版本: arm-linux-gcc 4.3.3
(2) Linux环境:redhat enterprise 5.5 (2.6.18-194.el5)
(3) 开发板:TQ2440
2. 编译busybox
(1) 获取busybox源码,放在/opt目录下,解压,进入busybox源码目录
#tar jxvf busybox-1.17.2.tar.bz2
#cd busybox-1.17.2
#vi Makefile
将164行改为CROSS_COMPILE = arm-linux-
将190行改为ARCH = arm
保存退出进入配置菜单
#make menuconfig 采用默认配置保存推出
#make
#make install
通过上面的步骤,在busybox-1.17.2的根目录下出现了一个_install目录,
在该目录下又有三个目录文件bin sbin usr和一个链接文件 linuxrc。
3. 创建根文件系统必要的目录
(1)在/opt目录下创建root_fs目录
#mkdir root_fs
#cd root_fs
(2)将busybox-1.17.2的根目录下_install中的bin sbin usr和linuxrc拷贝到root_fs
#cp -rf /opt/busybox-1.17.2/_install/* /opt/root_fs
(3)创建必要的目录
#mkdir dev etc home lib mnt opt proc root sys tmp var
(4)创建必要的二级目录
#mkdir usr/lib usr/share
#mkdir etc/rc.d
#mkdir var/lib var/lock var/run var/tmp
4. 创建必要的文件
(1) 获取库文件,(交叉编译工具下的库文件)到root_fs/lib目录中
#cp -rf /opt/arm/4.3.3/arm-none-linux-gnueabi/libc/armv4t/lib/*so* lib -a
(2) 将主机etc目录下的passwd、group、shadow文件拷贝到root_fs/etc目录下
#cp -f /etc/passwd /etc/group /etc/shadow etc
将目录/opt/busybox-1.17.2/examples/bootfloppy/etc下的所有文件拷贝到root_fs/etc下。
在这个目录下有三个文件fstab, inittab, profile和一个目录init.d,在目录init.d中有一个文件rcS。
#cp -rf /opt/busybox-1.17.2/examples/bootfloppy/etc/* etc
在目录etc下创建文件mdev.conf。mdev是?v的一个简化版本,
我们可以通过文件mdev.conf自定义一些设备节点的名称或链接来满足特定的需要,但在此处让它为空。
#touh etc/mdev.conf
(3)创建两个设备文件dev/console dev/null。
在linux内核源码文件init/main.c中有打开设备文件dev/console的操作如下:
static noinline int init_post(void)
__releases(kernel_lock)
{
………………………………
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.\n");
………………………………
}
内核启动执行到这里时mdev还没有构建dev目录,如果没有创建设备文件dev/console就将会打印警告
Warning: unable to open an initial console。
在内核启动的过程中要将产生的一些垃圾信息丢弃就需要空设备dev/null。
#mknod dev/console c 5 1
#mknod dev/null c 1 3
5. 修改文件
在启动过程中bootloader会传递参数init=/linuxrc给内核的main()函数,所以在文件系统被挂载后,
运行的第一个程序是linuxrc,而linuxrc是一个指向/bin/busybox的链接文件,也就是说文件系统被挂在后运行的第一个程序是busybox。
Busybox首先会解析文件/etc/inittab,这个文件中存放的是系统的配置信息,这些配置信息指明了接下来将要启动那些程序。
-------------------------------------------------------------------------------------------------------
(1)修改文件etc/inittab如下
::sysinit:/etc/init.d/rcS
s3c2410_serial0::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
说明:
/etc/inittab 文件中每个条目用来定义一个子进程,并确定它的启动方法,格式如下
:::
:表示这个进程要使用的控制台(即标准输入、标准输出、标准错误设备)。如果省 略,则使用与init进程一样的控制台。
:对于Busybox init程序,这个字段滑意义,可以省略。
:表示init程序如何控制这个子进程,
: 要执行的程序,它可以是可执行程序,也可以是脚本
文件etc/inittab配置条目说明如下:
::sysinit:/etc/init.d/rcS
启动系统初始化文件/etc/init.d/rcS。字段sysinit表明文件/etc/init.d/rcS在系统启动后最先执行,
并且只执行一次,init进程等待它结束才继续执行其它动作。(脚本文件名一般为rc,后缀S代表单用户运行级别脚本)
tq2440_serial0::askfirst:-/bin/sh
在串口s3c2410_serial0上启动askfirst动作的shell。
S3C2410的串口名在/dev下是s3c2410_serialx。askfirst表明init进程先输出 “Please press Enter to actvie this console”,
等用户输入回车键之后才启动-/bin/sh。
::ctrlaltdel:/sbin/reboot
当按下Ctrl+Alt+Delete组合键时,init重启执行程序。字段ctrlaltdel表明当按下Ctrl+Alt+Delete组合键时,执行相应的进程。
::shutdown:/bin/umount -a -r
告诉init在关机时运行umount命令卸载所有的文件系统,如果卸载失败,试图以只读方式重新挂载。
字段shutdown表明在重启关闭系统命令时执行相应进程。 ------------------------------------------------------------------------------------------------------------------------------
(2)当解析完文件etc/inittab后就将启动这些进程,首先要执行的是启动脚本etc/init.d/rcS。
修改文件etc/init.d/rcS如下:
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
/bin/hostname CPEmbed
/sbin/ifconfig lo 127.0.0.1 up
/sbin/ifconfig eth0 192.168.1.8 netmask 255.255.255.0
/sbin/route add default gw 192.168.1.1 eth0
echo "---------------mount all-----------------"
/bin/mount -a
mkdir /dev/pts
/bin/mknod /dev/pts/0 c 136 0
/bin/mknod /dev/pts/1 c 136 1
/bin/mknod /dev/pts/2 c 136 2
/bin/mknod /dev/pts/3 c 136 3
/bin/mknod /dev/pts/4 c 136 4
/bin/mknod /dev/pts/5 c 136 5
/bin/mount -t devpts devpts /dev/pts
echo /sbin/mdev>/proc/sys/kernel/hotplug
mdev -s
/usr/sbin/telnetd &
/usr/sbin/vsftpd &
echo "******************************************"
echo "******************************************"
echo "** Kernel version: linux-2.6.31.1 **"
echo "** Date: 2012.04.12 **"
echo "******************************************"
说明如下:
#! /bin/sh 用busybox的shell
PATH=/sbin:/bin:/usr/sbin:/usr/bin //shell命令的搜索路径
runlevel=S //运行在单用户模式
prevlevel=N //前一个级别为n表示没有前一个级别
umask 022 //权限位掩码
export PATH runlevel prevlevel //将设置的变量导出到环境中
/bin/hostname CPembed //主机名,CPembed将出现在shell提示符中[root@CPembed/]#
/sbin/ifconfig lo 127.0.0.1 up //启动lo
/sbin/ifconfig eth0 192.168.1.8 netmask 255.255.255.0 up //配置ip地址
/sbin/route add default gw 192.168.1.1 eth0 //添加默认路由
/bin/mount -a //将文件etc/fstab中指明的文件系统挂载到对应挂载点上
后面的8行是对telnetd的配置
echo /sbin/mdev>/proc/sys/kernel/hotplug //用mdev来处理内核的热插拔事件。
当有热插拔事件产生时,内核就会调用位于/sbin目录的mdev。这时mdev通过环境变量中的ACTION和DEVPATH,
(这两个变量是系统自带的)来确定此次热插拔事件的动作以及影响了/sys 中的那个目录。接着会看看这个目录中是否有“dev”的属性文件,
如果有就利用这些信息为 这个设备在/dev 下创建设备节点文件。
mdev -s //建立dev目录。以‘-s’为参数调用位于/sbin 目录写的 mdev(其实是个链接,作用是传递参数给/bin目录下的busybox 程序并调用它),mdev扫描 /sys/class 和/sys /block中所有的类设备目录,如果在目录中含有名为“dev”的文件,且文件中包含的是设备号,则 mdev 就利用这些信息为这个设备在/dev下创建设备节点文件。一般只在启动时才执行一次“mdev -s”
/usr/sbin/telnetd & //后台运行telnetd
/usr/sbin/vsftpd & //后台运行vsftpd
------------------------------------------------------------------------------------------------------------------------------
(3)修改文件etc/fstab如下:
#device mount-point type option mp fsck order
proc /proc proc defaults 0 0
none /tmp ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0
mdev /dev ramfs defaults 0 0
在系统启动初始化文件/etc/init.d/rcS中有执行挂载命令/bin/mount -a ,这便是将文件etc/fstab中指定 的文件系统挂载到对应的挂载点上。这些文件系统的挂在是执行mdev -s命令建立dev目录的前提------------------------------------------------------------------------------------------------------------------------------
(4)在启动脚本etc/init.d/rcS执行完后将在串口s3c2410_serial0启动一个shell。Shell启动过程中会根据文件/etc/profile配置登陆环境。
文件/etc/profile修改如下:
USER=" 'id -un' "
LOGNAME=$USER
PS1='[\u@\h \W]# '
PATH=$PATH
HOSTNAME='/bin/hostname'
export USER LOGNAME PS1 PATH
具体说明:
USER="id -un" //获取用户名id-un与whoami命令有相同的功能
PS1='[\u@\h \W]# ' //PS1指定sh提示符的格式在本环境下将是[root@cyembed /]#
export USER LOGNAME PS1 PATH 将这些变量导出到环境。
(5)在用户登录时将在/etc下寻找三个文件passwd ,shadow, group匹配相关信息。
这三个文件修改如下:
/etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
/etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
ftp:x:50:
nobody:x:99:
/etc/shadow root:$6$hnswPTgxzFaZHlLl$//:14819:0:99999:7:::
bin:*:14715:0:99999:7:::
daemon:*:14715:0:99999:7:::
ftp:*:14715:0:99999:7:::
nobody:*:14715:0:99999:7:::
------------------------------------------------------------------------------------------------------------
6. 制作yaffs2根文件系统镜像
用天嵌科技提供的yaffs2文件系统镜像制作工具mkyaffs2image,制作根文件系统镜像。
#./mkyaffs2image root_fs root_fs.bin
7. 将根文件系统镜像下载到nand flash并启动
启动信息如下:
❸ itop4412最小linux系统怎么挂载u盘
如果是iTop-4412的android4.0系统,可以这样来实现:
linux QT系统下挂载u盘,首先用命令mknod /dev/sda1 b 8 1创建U盘的设备节点,然后使用命令mount /dev/sda1 /mnt/udisk/挂载u盘即可。
❹ 如何在udev自动创建设备节点
创建设备文件的方法:
第一种是使用mknod手工创建:mknod filename type major minor
第二种是自动创建设备节点:利用udev(mdev)来实现设备文件的自动创建,首先应保证支持udev(嵌入式系统用mdev),由busybox配置。
udev介绍
udev 运行在用户模式,而非内核中。udev 的初始化脚本在系统启动时创建设备节点,并且当插入新设备——加入驱动模块——在sysfs上注册新的数据后,udev会创新新的设备节点。
udev 是一个工作在用户空间的工具,它能根据系统中硬件设备的状态动态的更新设备文件,包括设备文件的创建,删除,权限等。这些文件通常都定义在/dev 目录下,但也可以在配置文件中指定。udev 必须内核中的sysfs和tmpfs支持,sysfs 为udev 提供设备入口和uevent 通道,tmpfs 为udev 设备文件提供存放空间。
注意,udev 是通过对内核产生的设备文件修改,或增加别名的方式来达到自定义设备文件的目的。但是,udev 是用户模式程序,其不会更改内核行为。也就是说,内核仍然会创建sda,sdb等设备文件,而udev可根据设备的唯一信息来区分不同的设备,并产生新的设备文件(或链接)。而在用户的应用中,只要使用新产生的设备文件
❺ 字符设备有两个设备的时候,怎么读第二个设备
字符设备驱动程序框架
1、写出open、write函数
2、告诉内核
1)、定义一个struct file_operations结构并填充好
static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_mole变量 */
.open = first_drv_open,
.write = first_drv_write,
};
2)、把struct file_operations结构体告诉内核
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核
相关参数:第一个,设备号,0自动分配主设备号,否则为主设备号0-255
第二个:设备名
第二个:struct file_operations结构体
4)、register_chrdev由谁调用(入口函数调用)
static int first_drv_init(void)
5)、入口函数须使用内核宏来修饰
mole_init(first_drv_init);
mole_init会定义一个结构体,这个结构体里面有一个函数指针指向first_drv_init这个函数,当我们加载或安装一个驱动时,内核会自动找到这个结构体,然后调用里面的函数指针,这个函数指针指向first_drv_init这个函数,first_drv_init这个函数就是把struct file_operations结构体告诉内核
6)、有入口函数就有出口函数
mole_exit(first_drv_exit);
最后加上协议
MODULE_LICENSE("GPL");
3、mdev根据系统信息自动创建设备节点:
每次写驱动都要手动创建设备文件过于麻烦,使用设备管理文件系统则方便很多。在2.6的内核以前一直使用的是devfs,但是它存在许多缺陷。它创建了大量的设备文件,其实这些设备更本不存在。而且设备与设备文件的映射具有不确定性,比如U盘即可能对应sda,又可能对应sdb。没有足够的主/辅设备号。2.6之后的内核引入了sysfs文件系统,它挂载在/sys上,配合udev使用,可以很好的完成devfs的功能,并弥补了那些缺点。(这里说一下,当今内核已经使用netlink了)。
udev是用户空间的一个应用程序,在嵌入式中用的是mdev,mdev在busybox中。mdev是udev的精简版。
首先在busybox中添加支持mdev的选项:
Linux System Utilities --->
[*] mdev
[*] Support /etc/mdev.conf
[*] Support subdirs/symlinks
[*] Support regular expressions substitutions when renaming device
[*] Support command execution at device addition/removal
然后修改/etc/init.d/rcS:
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
执行mdev -s :以‘-s’为参数调用位于 /sbin目录写的mdev(其实是个链接,作用是传递参数给/bin目录下的busybox程序并调用它),mdev扫描 /sys/class 和 /sys/block 中所有的类设备目录,如果在目录中含有名为“dev”的文件,且文件中包含的是设备号,则mdev就利用这些信息为这个设备在/dev 下创建设备节点文件。一般只在启动时才执行一次 “mdev -s”。
热插拔事件:由于启动时运行了命 令:echo /sbin/mdev > /proc/sys/kernel/hotplug ,那么当有热插拔事件产生时,内核就会调用位于 /sbin目录的mdev。这时mdev通过环境变量中的 ACTION 和 DEVPATH,来确定此次热插拔事件的动作以及影响了/sys中的那个目录。接着会看看这个目录中是否“dev”的属性文件,如果有就利用这些信息为 这个设备在/dev 下创建设备节点文件
重新打包文件系统,这样/sys目录,/dev目录就有东西了
下面是create_class的原型:
#define class_create(owner, name) /
({ /
static struct lock_class_key __key; /
__class_create(owner, name, &__key); /
})
extern struct class * __must_check __class_create(struct mole *owner,
const char *name,
struct lock_class_key *key);
class_destroy的原型如下:
extern void class_destroy(struct class *cls);
device_create的原型如下:
extern struct device *device_create(struct class *cls, struct device *parent,
dev_t devt, void *drvdata,
const char *fmt, ...)
__attribute__((format(printf, 5, 6)));
device_destroy的原型如下:
extern void device_destroy(struct class *cls, dev_t devt);
具体使用如下,可参考后面的实例:
static struct class *firstdrv_class;
static struct class_device *firstdrv_class_dev;
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
下面再来看一下应用程序如何找到这个结构体的
在应用程序中我们使用open打开一个设备:如:open(/dev/xxx, O_RDWR);
xxx有一个属性,如字符设备为c,后面为读写权限,还有主设备名、次设备名,我们注册时 通过register_chrdev(0, "first_drv", &first_drv_fops)(有主设备号,设备名,struct file_operations结构体)将first_drv_fops结构体注册到内核数组chrdev中去的,结构体中有open,write函数,那么应用程序如何找到它的,事实上是根据打开的这个文件的属性中的设备类型及主设备号在内核数组chrdev里面找到我们注册的first_drv_fops,
实例代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static struct class *firstdrv_class;
static struct class_device *firstdrv_class_dev;
volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL;
static int first_drv_open(struct inode *inode, struct file *file)
{
//printk("first_drv_open\n");
/* 配置GPF4,5,6为输出 */
*gpfcon &= ~((0x3<<(4*2)) | (0x3<<(5*2)) | (0x3<<(6*2)));
*gpfcon |= ((0x1<<(4*2)) | (0x1<<(5*2)) | (0x1<<(6*2)));
return 0;
}
static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val;
//printk("first_drv_write\n");
_from_user(&val, buf, count); // _to_user();
if (val == 1)
{
// 点灯
*gpfdat &= ~((1<<4) | (1<<5) | (1<<6));
}
else
{
// 灭灯
*gpfdat |= (1<<4) | (1<<5) | (1<<6);
}
return 0;
}
static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_mole变量 */
.open = first_drv_open,
.write = first_drv_write,
};
int major;
static int first_drv_init(void)
{
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
gpfdat = gpfcon + 1;
return 0;
}
static void first_drv_exit(void)
{
unregister_chrdev(major, "first_drv"); // 卸载
class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
iounmap(gpfcon);
}
mole_init(first_drv_init);
mole_exit(first_drv_exit);
MODULE_LICENSE("GPL");
编译用Makefile文件
KERN_DIR = /work/system/linux-2.6.22.6
all:
make -C $(KERN_DIR) M=`pwd` moles
clean:
make -C $(KERN_DIR) M=`pwd` moles clean
rm -rf moles.order
obj-m += first_drv.o
测试程序:
#include
#include
#include
#include
/* firstdrvtest on
* firstdrvtest off
*/
int main(int argc, char **argv)
{
int fd;
int val = 1;
fd = open("/dev/xyz", O_RDWR);
if (fd < 0)
{
printf("can't open!\n");
}
if (argc != 2)
{
printf("Usage :\n");
printf("%s \n", argv[0]);
return 0;
}
if (strcmp(argv[1], "on") == 0)
{
val = 1;
}
else
{
val = 0;
}
write(fd, &val, 4);
return 0;
}
❻ 如何使mdev可以在/dev/下建立设备节点
在busybox源代码的 doc/mdev.txt 文档里面找到以下说明: 怎么能让mdev把设备节点创建在子目录下呢?
在busybox源代码的 doc/mdev.txt 文档里面找到以下说明:
You can rename/move device nodes by using the next optional field.
<device regex> <uid>:<gid> <permissions> [=path]
So if you want to place the device node into a subdirectory, make sure the path
has a trailing /. If you want to rename the device node, just place the name.
hda 0:3 660 =drives/
This will move "hda" into the drives/ subdirectory.
hdb 0:3 660 =cdrom
This will rename "hdb" to "cdrom".
Similarly, ">path" renames/moves the device but it also creates
a direct symlink /dev/DEVNAME to the renamed/moved device.
所以, 我们只要在 /etc/mdev.conf配置文件里面加入几行就可以了:
controlC[0-9] 0:0 0660 =snd/
pcm.* 0:0 0660 =snd/
seq.* 0:0 0660 =snd/
mix.* 0:0 0660 =snd/
timer 0:0 0660 =snd/
这样再运行mdev, ALSA相关的设备节点就都创建在 /dev/snd/ 目录下了。
后记: 内核里面 struct class 里面的 devnode 项跟设备节点所在目录好像也有关系。
❼ echo /sbin/mdev> /proc/sys/kernel/hotplug什么意思
应该是loglevel的问题,通过下面命令查看你当前的loglevel设置。 cat /proc/sys/kernel/printk 如果想什么都打印出来,就 echo 8 > /proc/sys/kernel/...
❽ 如何让udev自动建立设备文件
创建设备文件的方法: 第一种是使用mknod手工创建:mknod filename type major minor 第二种是自动创建设备节点:利用udev(mdev)来实现设备文件的自动创建,首先应保证支持udev(嵌入式系统用mdev),由busybox配置。
❾ 创建节点目录时不需要拷贝公链下的哪个文件
摘要 A您好,我正在帮您查询相关的信息,马上回复您。
❿ android sensor怎样创建设备节点
在Android中,由于没有mdev和udev,所以它没有办法动态的生成设备节点,那么它是如何做的呢?
我们可以在system/core/init/下的init.c和devices.c中找到答案:
init.c中

在Android中,没有独立的类似于udev或者mdev的用户程序,这个功能集成到了init中做了。代码见:system/core/init/init.c文件,如下:
if (ufds[0].revents == POLLIN)
handle_device_fd(device_fd);
其中handle_device_fd(device_fd)函数在system/core/init/devices.c中实现,参数device_fd 由函数device_init()->open_uevent_socket()->socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)函数调用返回。
函数handle_device_fd(device_fd)中,根据传进来的device_fd参数,调用recv(fd, msg, UEVENT_MSG_LEN, 0)函数,将内核探测到的设备并通过NETLINK机制传过来的socket描述符转化成消息。接着调用parse_event(msg, &uevent);函数将消息翻译成uevent事件,并将改事件传递给handle_device_event(&uevent)函数。
handle_device_event(&uevent)函数中,依据参数uevent->subsystem类型创建dev下的相应目录,如:/dev/graphics。紧接着根据uevent->action是"add"还是"remove"来实现设备节点的创建与删除。如果uevent->action是"add",则调用make_device(devpath, block, uevent->major, uevent->minor)函数生成设备节点。如果uevent->action是"remove",则调用unlink(devpath)对设备节点进行删除。