摘要
对于使用register_chrdev()去注册字符设备的driver,在insmod加载完driver后还需要通过mknod去创建对应的设备节点,否则应用程序或调用库无法去open设备。
但是,当一个driver需要创建非常多的设备节点时,通过在rc文件中去逐个mknod显然不合理。因此,较合理的做法就是通过程序或脚本去批量创建设备节点。
简单示例
- 头文件定义
- 自定义一个结构体将设备节点名称、设备类别(字符设备、块设备)、主设备号、次设备号以及节点操作权限。
- 自定义一个在/dev下要创建的目录(设备节点所在的二级目录),没有则不需要定义。
/*
** sample.h
*/
#ifndef __SAMPLE_H__
#define __SAMPLE_H__
static const struct device_struct {
char *name;
char type;
int major;
int minor;
int mode;
} device_list[] = {
{ "hello/hi0", 'c', 168, 0, 0660},
{ "hello/hi1", 'c', 168, 1, 0660},
...
{ "hello/hi198", 'c', 168, 198, 0660},
{ "hello/hi199", 'c', 168, 199, 0660},
...
};
#define N_DEVICE_LIST (sizeof(device_list)/sizeof(device_list[0]))
static const char * const dir_list[] = {
"hello",
...
};
#define N_DIR_LIST (sizeof(dir_list)/sizeof(dir_list[0]))
#endif
- 源文件定义
- 首先,进程将目录切换到/dev目录下
- 然后,创建二级目录并设置操作权限
- 创建设备ID,设置设备权限,是字符设备则追加S_IFCHR权限(若是块设备则为S_IFBLK)
- 创建设备节点
- 返回根目录,完成task
/*
** sample.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/kdev_t.h>
#include "sample.h"
#define TARGET_PATH "/dev"
#define UNUSED(a) (a)
int devastate(void)
{
unsigned int i;
char dev_name[64];
/*
* chdir(const char *path) changes the current working directory of the calling process to the directory specified in path.
*/
if (chdir(TARGET_PATH)) {
printf("change directory failed...");
return -1;
}
/*
* mkdir(const char *pathname, mode_t mode) creates the directory named pathname with attributes specified by mode.
* chmod(const char *path, mode_t mode) changes the permissions of path file with attributes specified by mode.
*/
for (i = 0; i < N_DIR_LIST; i++) {
if (mkdir(dir_list[i], 0755) < 0) {
printf("mkdir failed...");
} else {
chmod(dir_list[i], 0755);
}
}
/*
* MKDEV(ma,mi) generates a device ID use major and minor.
* mknod(const char *pathname, mode_t mode, dev_t dev) creates a filesystem node (file, device special file or named pipe)
* named pathname, with attributes specified by mode and dev.
*/
for (i = 0; i < N_DEVICE_LIST; i++) {
unsigned int dev = MKDEV(device_list[i].major, device_list[i].minor);
int mode = S_IFCHR | device_list[i].mode;
if (mknod(device_list[i].name, mode, dev) < 0) {
printf("mknodfailed...");
} else {
sprintf(dev_name, "%s/%s", TARGET_PATH, device_list[i].name);
chmod(dev_name, mode);
}
}
chdir("/");
return 0;
}
int main(int argc, char **argv)
{
UNUSED(argc);
UNUSED(argv);
return devastate();
}