内核源码目录,第一个目录——顶层目录,如下
内核编译:makefile
一、条件编译
自己编译内核步骤
1.cp config_mini2440_td355.config 第一次编译内核(仅一次)
2.make menuconfig 每次有文件增删时
3.make uImage 每次编译
4. 拷贝新的uImage至tftpboot目录下,替换旧的uImage(把旧的删了)
5. 重新下载内核(tftp 0x30008000 uImage),下载成功后再启动(bootm 30008000),无报错,即成功
错误
make uImage时提示信息
启动时,提示错误信息
错误处理
1. 修改入口地址entry point
2. 修改之后重新编译
3. 重新make uImage,拷贝uImage,再重新下载内核(tftp 0x30008000 uImage),启动内核
无报错直接启动后即正确启动。
错误原因
Image ---- 可以直接使用的内核映像
zImage ---- 一段解压程序+Image的压缩包
uImage ---- 64字节的头信息(压缩类型,大小) + zImage
原因:头信息不能运行,得偏移过去64字节才能开始运行,64字节 = 0x40 ,
所以入口地址(entry load) 比 加载地址(load address) 多0x40。
即正确:laod address = 0x30008000,entry point = 0x30008040。
二、编写自己的Kconfig
创建一个config
向内核写新目录步骤
1. 自己写一个目录
在目录 ~/linux-2.6.32.2/drivers/char 下创建一个新文件 kcf,然后 vi Kconfig,即可编写
2. 得在Kconfig里面“声明”一下,menuconfig才会显示
去到上一层目录 ~/linux-2.6.32.2/drivers/char,在原本的 Kconfig “声明”一下,才可生效
3. 在menuconfig界面查看config结果
打开界面查看结果(make meunconfig)
4. 配置选项后,到 ~/linux-2.6.32.2 .config查看配置结果
在 ~/linux-2.6.32.2 目录下 vi .config,查看配置结果
三、向内核新增文件
步骤:=gcc
menuconfig选中新选项,成功提示
在menuconfig里不选中选项,重新下载uImage,拷贝至tftpboot,内核下载,开机后显示:
四、驱动
驱动(程序):驱使设备行动的程序
驱动程序要素:
- 确定一个设备号
- 实现必要的系统调用方法(open、read...)
- 绑定设备号和对应的操作方法
- 向内核注册该驱动节点
驱动模板
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/cdev.h>
#define MAJOR_NUM 255
#define MINOR_NUM 0
#define DEV_NAME "demo"
static int open(struct inode * node, struct file * file)
{
printk("demo open ...\n");
return 0;
}
static ssize_t read(struct file * file, char __user * buf, size_t len, loff_t * loff)
{
printk("demo read ...\n");
return 0;
}
static ssize_t write(struct file * file, const char __user * buf, size_t len, loff_t * loff)
{
printk("demo write ...\n");
return 0;
}
static int close(struct inode * node, struct file * file)
{
printk("demo close ...\n");
return 0;
}
static dev_t dev_num;
static struct cdev dev;
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = open,
.read = read,
.write = write,
.release = close
};
static int __init demo_init(void)
{
int ret = 0;
dev_num = MKDEV(MAJOR_NUM, MINOR_NUM); ;//(MAJOR_NUM << 20) | MINOR_NUM;
ret = cdev_add(&dev, dev_num, 1);
if(ret < 0)
goto err1;
cdev_init(&dev, &fops);
ret = register_chrdev_region(dev_num, 1, DEV_NAME);
if(ret < 0)
goto err2;
printk("demo_init ###############################\n");
return 0;
err1:
cdev_del(&dev);
printk("demo cdev_add failed ret = %d\n", ret);
return ret;
err2:
unregister_chrdev_region(dev_num, 1);
cdev_del(&dev);
printk("demo register_chrdev_region failed ret = %d\n", ret);
return ret;
}
static void __exit demo_exit(void)
{
unregister_chrdev_region(dev_num, 1);
cdev_del(&dev);
printk("demo_exit ###############################\n");
}
module_init(demo_init);
module_exit(demo_exit);
设备号: 32位的数字
高12位 主设备号 设备类型
低12位 次设备号 同类设备的编号
运行之前,手动创建设备节点:
mknod /dev/demo c 255 0
// /dev/demo-设备节点名 c-设备类型 255-主设备号 0-次设备号
第一个字符--文件属性
ls -l 命令列出文件或目录的详细信息时,第一个字符代表文件或目录的类型
- -:普通文件
- d:目录
- c:字符设备文件。字符设备文件允许访问硬件设备,通常一次处理一个字符,如终端。
数据的访问是顺序的 (字节流形式) - b:块设备文件。也是访问硬件设备,以块为单位进行数据传输,如硬盘、软盘。
数据访问可以是随机的,一般是存储设备 - l:符号链接,软连接。类似于快捷方式,指向另一个文件或目录。
- s:套接字文件
只有名字,会集成复杂的协议 - p:管道文件
五、ctag用法
ctrl + ] 进去
ctrl + o/t 出来