linux内核驱动的知识要点

摘要:
IT信息技术研究的本质工业计算机0和1:数字计算一切的数字描述数字基础:1024127601620和1可以描述一切的作用内存:1.内存指令2。存储器数据CPU的组成:ALU(算术单元)控制器寄存器ALU包含许多计算电路:每个电路对应于一条指令。CPU被划分为RISC(精简指令集):容易、低功耗、低CISC(复杂指令集)。难、快、高CPU-从存储器-抽屉执行指令的过程:1。值(从存储器读取指令:打开

IT的本质
信息技术
研究0和1的行业

计算机:数字计算

数字描述万事万物

数字的进制:10 24 12 7 60 16 2

0和1可以描述万事万物

内存的作用:
1. 存指令
2. 存数据

CPU的组成:ALU(运算器) 控制器 寄存器
ALU中包含很多个运算电路:每个电路对应一条指令


CPU分为:
RISC(精简指令集):易 慢 功耗低
CISC(复杂指令集):难 快 高


CPU——奴隶 内存——抽屉
执行一条指令的过程:
1. 取值(从内存中读取指令:打开抽屉取出写着指令的纸条)
2. 译码(从二进制指令中解析出操作码以决定后面使用哪条运算电路:读懂纸条上的指令以便知道后面要做什么)
3. [取数据](从内存中读取数据:打开抽屉取出后面所做事情所需的原材料)
4. 执行(执行运算电路:完成所要做的事情)
5. [存数据](运算电路产生的结果存储到内存:所做动作产生的结果存放到抽屉)

老冯的精髓贡献:
1. 二进制思想
计算机世界里的一切信息 = 二进制位 + 上下文

数据类型:
1. sizeof
2. 变量定义语句的作用
3. 相关的运算
4. 作为函数形参类型
5. 作为函数返回值类型
数据类型就是对内存中二进制位的上下文描述
文件格式就是对外存中二进制位的上下文描述
网络协议就是对网络中传输的二进制位的上下文描述

2. 程序存储思想
程序在执行之前先将指令存放到内存
函数指针
进程的内存布局:
a. 栈区:非static的局部变量 函数形参
b. 堆区:动态分配
c. 数据区:static的局部变量 全局变量 字符串常量
d. 代码区:二进制指令


多核:
并行编程:多任务编程
伪并行:分时
真并行:


ARM:
1. 公司名
2. 技术专利名称
3. 一系列CPU的统称

寻址空间:26位
两种指令集:ARM指令集 Thumb指令集
Cortex A(应用) R(实时性) M(单片机)

Cache高速缓存
MPU:内存保护单元
MMU:内存管理单元
虚拟内存

虚拟地址&物理地址


汇编:
1. 寄存器
2. 寻址方式

r0~r12

r13(SP):堆栈寄存器
r14(LR):链接寄存器
r15(PC程序计数器):指向空间存放的是要被取指的指令
C-PSR:当前程序状态寄存器
S-PSR:备份CPSR内容


执行流:
1. 任务流(进程、线程)
2. 异常流


编译过程: 预处理 编译 汇编 链接


ST:写内存
LD:读内存
SWP:交换


数据结构:研究如何组织、管理、存储多个同类型数据以及相关操作的学科

1. 逻辑关系
集合
线性关系:一对一 线性表 栈 队列
树形关系:一对多
图形关系:多对多
2. 存储方式
顺序存储
链式存储


执行流
顺序执行
跳转执行:
选择
分支
循环
函数调用
break
continue
return
goto


test.S:
AREA ttt,CODE,READONLY
ENTRY
MOV r0,#1
MOV r1,#2
ADD r2,r0,r1
END

64位linux编译运行32位app的支持:
sudo apt-get install build-essential module-assistant
sudo apt-get install gcc-multilib g++-multilib
sudo apt-get install lib32ncurses5 lib32z1
验证:
gcc hello.c -o hello -Wall -m32

RS232
启动模式选择开关:
1. SD卡
2. NandFlash启动(靠铜柱)

开发板的名字:Tiny210
CPU:S5PV210(SOC)三星
ARM核:Cortex-A8
RAM:512M
NandFlash:512M


格式化:给分区指定文件系统
文件系统:FAT32 NTFS ext4 yaffs2
文件内容
文件名
元信息

bootloader:一类裸机程序
1. 启动操作系统
2. 安装操作系统

Superboot


安装系统需要安装:
1. bootloader
2. OS
3. 根文件系统rootfs

1. cd
2. mkdir arm210
3. cd arm210
4. mkdir bin src
5. cp ???/src/tiny210...tgz ./src
6. cd src
7. tar zxvf tiny210...tgz
8. mv tiny210... u-boot

9. 安装交叉编译器
a. sudo cp ???/tools/arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz /opt
b. cd /opt
c. sudo tar zxvf arm-linux...tgz
d. cd opt/FriendlyARM/toolschain/4.5.1/bin/
e. pwd后拷贝路径
f. cd
g. 修改~/.bashrc
最后添加两行:
export ARM_GCC_BIN=粘贴拷贝的路径
export PATH=$PATH:$ARM_GCC_BIN
保存退出
h. 关闭控制台,重启控制台
i. 命令行敲arm加两次Tab键,出现一堆arm开头的信息说明安装OK

u-boot:
1. 如何编译uboot
cd ~/arm210/src/u-boot
make distclean
make tiny210_config
make all
cp ./tools/mkimage ../../bin/
cp tiny210-uboot.bin ../../bin/
2. 如何安装uboot
A. 用SD卡第一分区中的Superboot安装
1) 拷贝 ~/arm210/bin/tiny210-uboot.bin 到 sd卡/images目录中
2) 修改FriendlyARM.ini文件,注释掉安装zImage、内核参数、rootfs的三行
3) 模式开关置于SD卡启动一侧
4) 开发板加电,自动完成uboot的安装
5) 安装成功后关闭电源,模式开关置于Nandflash启动一侧
6) 重新加电,在SecureCRT中看到uboot命令行说明OK
B. 用Nandflash第一分区安装好的uboot安装
一、下载tiny210-uboot.bin到内存
a. 方法1:串口下载
1) 将编译好的tiny210-uboot.bin拷贝到windows
2)【uboot命令行】loady 21000000
3) SecureCRT菜单Transfer中选Send Ymodem
4) 点击Send Ymodem出现的界面中选中tiny210-uboot.bin
5) 点击ADD按钮然后点击OK按钮开始传送
b. 方法2:SD卡下载
1)将要下载的文件copy到sd卡根目录
2)将sd插入开发板
3)【uboot命令行】mmc part
命令查看是第几个sd卡(一般为0),和该SD卡的FAT分区是第几个分区(一般为1)
4)【uboot命令行】fatload mmc 0:1 21000000 sd卡中要下载的文件名
二、擦除NandFlash第一分区
【uboot命令行】nand erase 0 0x600000
三、将内存中的tiny210-uboot.bin写到NandFlash第一分区
【uboot命令行】nand write 0x21000000 0 0x600000
3. 如何使用uboot
两种工作模式:
boot:默认模式
loader:加电时SecureCRT界面敲空格进入uboot命令行
4. uboot源码的两个阶段:
汇编阶段
C阶段


Linux内核:
1. 如何编译Linux内核
sudo apt-get install libncurses5-dev
cp ???/src/linux-3.0.8-20130327.tgz ~/arm210/src
cd ~/arm210/src
tar zxvf linux-3.0.8-20130327.tgz
cd linux-3.0.8

make distclean
cp mini210_linux_defconfig .config
make menuconfig
界面中去掉:
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
<*>NAND Device Support --->
[ ]S3C NAND Hardware ECC
界面中选中:
File systems --->
[*] Miscellaneous filesystems --->
[*] Lets Yaffs do its own ECC
修改源码:
drivers/mtd/nand/s3c_nand.c:1194行,_SOFT为_NONE

make 开始编译
cp arch/arm/boot/zImage ../../bin
cd ../../bin
./mkimage -n 'Hiro' -A arm -O linux -T kernel -C none -a 0x21000000 -e 0x21000040 -d ./zImage ./uImage

2. 如何安装Linux内核
串口或SD卡下载uImage到内存(步骤同uboot下载)
擦除第二分区:
【uboot命令行】nand erase 0x600000 0x500000
将内存中的uImage写到Nandflash第二分区
【uboot命令行】nand write 0x21000000 0x600000 0x500000

如果无法启动Linux内核,请设置uboot的启动命令:
【uboot命令行】setenv bootcmd "nand read 21000000 600000 500000;bootm 21000000"
【uboot命令行】saveenv
3. uImage的组合过程
4. Linux内核源码结构解析
任务管理 内存管理 设备管理
网络管理 文件管理 启动管理

根文件系统:
1. 如何制作根文件系统的img文件(镜像文件)
cd ~/arm210/bin
cp ???/tools/rootfs_qtopia_qt4-20130222.tar.gz ./
cp ???/tools/mkyaffs2image-128M ./
chmod +x ./mkyaffs2image-128M
sudo tar zxvf rootfs_qtopia_qt4-20130222.tar.gz
sudo mv rootfs_qtopia_qt4 rootfs
cd rootfs/opt
sudo rm * -rf
cd ../usr/local
sudo rm *.gz Trolltech/ -rf
cd ~/arm210/bin
sudo ./mkyaffs2image-128M ./rootfs rootfs.img

2. 如何安装根文件系统
SD卡下载rootfs.img到内存(步骤同uboot或uImage下载)
擦除第四分区:
【uboot命令行】nand erase 0xe00000 0xf200000
将内存中的rootfs.img写到Nandflash第四分区
【uboot命令行】nand write.yaffs 0x21000000 0xe00000 0x5BEB100 (rootfs.img文件大小的十六进制)

需求分析
设计
编码:20%
测试

维护

编程思想体现解决问题的第一思维:
面向过程:步骤化
结构化:模块化
面向对象:对象化


SE:
TE:
SPM:
SQA:
SCM:软件配置管理


ARM-Linux App:
1. 编译app:
arm-linux-gcc ???.c -o 可执行文件名 -Wall
2. 下载并执行app:
a. 串口下载
将编译好的可执行文件拷贝到windows文件系统
【开发板Linux命令行】cd /opt
【开发板Linux命令行】rx 可执行文件名
SecureCRT界面中点菜单Transfer,再选Send Xmodem
点Send Xmodem后的界面中选中要下载的文件,点击Add按钮,再点击OK按钮开始传送直到结束
【开发板Linux命令行】chmod +x 可执行文件名
【开发板Linux命令行】./可执行文件名
b. SD卡下载
将编译好的可执行文件拷贝到windows文件系统
自己电脑上插入SD卡
将已拷贝到windows文件系统的可执行文件拷贝到SD卡
将SD卡插入开发板
【开发板Linux命令行】cd /sdcard (该目录即为SD卡中的内容)

UNIX家族的三大分支:
1. System 5:AIX HPUX
2. BSD:FreeBSD NetBSD OpenBSD
3. 类UNIX:Linux、Minix


if(likely(x > y))
{
....
}


执行流:
1. 任务流(任务上下文)
a. 进程上下文
b. 应用线程上下文
c. 内核线程上下文
2. 异常流(异常上下文)


Linux命令:
1. 外部命令
2. 内部命令


switch()
{
case 1:
/*fall though*/
case 2:
}

函数定义的作用:
1. 代码复用
2. 简化逻辑
3. 拼装

语句:
1. 执行语句
独立语句
复合语句

2. 非执行语句


#define SWAP x=y;y=2;

if(a>b)
SWAP

int i
char c
long l
short s
float f
double d
T * p
struct st
union un
enum e
array a

double *T

typedef int INTARR5[5];

INTARR5 arr1;

typedef signed char INT8;
typedef short INT16;
typedef int INT32;
typedef long INT64;

x += 2;


#pragma pack(n)


int *(*a[5])(int,char *);

void (*b[10])(void (*)());

double(*)() (*e)[9];


int a;
int *pa;
int (*pa)[5];


向linux源码driver/char/目录里添加自己的代码并编译到zImage中:
1. 编写好代码
2. 在同级目录下Kconfig文件中找到雷同内容进行修改:
1)修改config 后的名字(将用在下面的Makefile文件中)
2) 修改config下一行“”中的内容(将被显示在make menuconfig界面)
3)help下一行内容,选择性修改
3. 在同级目录下Makefile文件中找到雷同内容行进行修改:
obj-$(CONFIG_XXX) += YYY.o
(XXX为Kconfig文件对应内容第一行config后面的名字)
(YYY为新增.c文件的文件名,注意不含.c扩展名)
4. 执行make menuconfig进入:
Device Drivers----->
Character devices------>
找到有(new)的哪一行,敲空格键将该项的值选为<*>或[*]
退出make menuconfig界面时记得选择Yes进行保存修改
5. 重新编译zImage:make
6. cp arch/arm/boot/zImage ../../bin
7. 将zImage制作成uImage:(下面的命令是在同一行)
./mkimage -n 'Hiro' -A arm -O linux -T kernel -C none -a 0x21000000 -e 0x21000040 -d ./zImage ./uImage
8. 将uImage下载安装Nandflash的第二分区

内核模块基础源码解析
内核模块代码编译
cd ~/arm210/src/linux3.0.8/
cp drivers/char/myhello.c ~/arm210/src/mydriver/hello/
cd ~/arm210/src/mydriver/hello/
编写或修改Makefile
make (有???.ko文件生成说明编译OK,否则要么Makefile有问题,要么C语言源码有问题)

插入、查询和移除内核模块
1. 开发板进入Linux命令行
2. 下载???.ko文件到开发板Linux的/opt目录下(下载方法同app可执行文件)
3. 插入、查询和移除内核模块的命令:
插入内核模块:insmod ???.ko
查询已被插入到内核的模块名:lsmod
移除已被插入到内核的模块:rmmod 模块名(lsmod显示的模块名,不是???.ko文件名)


内核模块参数
模块间的依赖


GPL
LGPL

开源软件 免费


make:制作
Makefile makefile

1. 编译命令过长
2. 编译时间过长

主体:规则
规则的组成:
目标:依赖列表
[Tab]怎么样用依赖产生目标的命令


.c源码编译可以生成:
1. app可执行文件
2. 库文件
静态库:windows下.lib UNIX家族OS下:.a
动态库:windows下.dll UNIX家族OS下:.so (共享库)
3. 裸机可执行文件
4. Linux内核模块文件:.ko

设备驱动程序:
外设:(辅助设备)按设备功能来分
1. 输入设备
2. 输出设备
3. 存储设备(外存)
4. 控制设备

外设:数据交互方式来分
1. 字符设备:按字节顺序存取
2. 块设备:按扇区(512字节)随机存取
3. 网络设备

linux下文件种类:
1. -:普通文件
2. d: 目录
3. l: link文件
4. p: 命名管道
5. s: 本地socket
6. c:字符设备 /dev
7. b:块设备 /dev

struct MyDev
{
struct cdev t;
....
}

内核里用链表将所有字符设备管理起来

每个设备在内核里都有唯一的身份标识:
1. 主设备号:哪一类设备
2. 次设备号:哪一个设备


globalmem:用内核空间中一块内存模拟一个简单的字符设备


指针类型的形参:
1. 值参数 (只读指向空间)
2. 结果参数(只向指向空间写结果)
3. 值-结果参数 (既从指向空间读数据又向指向空间写结果)


内存操作错误:
1. 野值(不确定值)
2. 野指针(不确定地址值)
3. 内存泄漏
4. 重复释放
5. 越界
6. 修改了只读数据区

C语言编程的最基本原则:
1. 类型一致化
2. 所有内存空间必须是已知可控的

描述符
标识符

int型的函数返回值:
1. 0表示调用正常,非0(负数更常用)表示发生了某种错误
2. 表示是或不是什么东东(bool)
3. 表示某个实际意义的整型数

C库函数:fopen ----->open
fclose ----->close
fprintf fputs fputc fwrite --->write
fscanf fgets fgetc fread --->read
fseek ftell ----->lseek
系统调用: open close read write lseek


arm210/src/mydriver/globalmem/globalmem.c
验证globalmem驱动程序:
1. 编译成ko文件
2. ko下载到开发板linux系统下的/opt目录里
3. 插入内核模块
4. 获取主设备号
cat /proc/devices | grep globalmem
5. 创建设备文件
mknod /dev/globalmem c 主设备 0
6. 编写App来验证驱动程序中各个函数

int main()
{
int fd = -1;
char buf[16] = "";
fd = open("/dev/globalmem",O_RDWR);
if(fd < 0)
{
printf("OPen failed ");
return 1;
}
write(fd,"hello",5);
lseek(fd,0,SEEK_SET);
read(fd,buf,5);
printf("buf=%s ",buf);

ioctl(fd,1,0);
memset(buf,0,16);
read(fd,buf,5);
printf("buf=%s ",buf);

close(fd);
return 0;
}


globalmem的缺陷:
1. 读写操作不支持阻塞
2. 不支持多任务共同使用

链表分类:
1. 指针域成员的个数
2. 有没有首尾相接
3. 有头结点的链表和无头结点的链表

头指针:


select:多路复用

int ret = -1;
fd_set rfds;
struct timeval tout = {0};
while(1)
{
求最大的文件描述符maxfd
FD_ZERO(&rfds);
FD_SET(fd1,&rfds);
FD_SET(fd2,&rfds);
.....
FD_SET(fdn,&rfds);
tout.tv_sec = 10;
ret = select(maxfd+1,&rfds,NULL,NULL,&tout);
if(ret < 0)
{
出错处理
}
if(FD_ISSET(fd1,&rfds))
{
从fd1中读数据
处理数据
}
if(FD_ISSET(fd2,&rfds))
{
从fd2中读数据
处理数据
}
........
if(FD_ISSET(fdn,&rfds))
{
从fd1中读数据
处理数据
}
}

免责声明:文章转载自《linux内核驱动的知识要点》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇c#读入,写入文本文件CSS/让一个盒子消失的5中方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

linux 命令行出现-bash-4.2$的解决办法

输入这两句话,然后关闭终端,重新登录一下就好了 cp /etc/skel/.bashrc /root/ cp /etc/skel/.bash_profile /root/ 同样的方法,如果是非root而是某用户,就把目标路径换成相对应的用户路径即可。 这两个文件通常在建立用户目录是自动添加,如果是你手动创建文件夹在/etc/passwd指定目录也会出现该错...

Linux配置阿里epl源

去阿里云 有源仓库 阿里云镜像官方站点https://developer.aliyun.com/mirror/ 先备份本机上的源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 根据对应版本下载新的 CentOS-Base.repo 到 /etc/...

linux磁盘空间满了 但是没有大文件

很常见的一个问题  linux磁盘空间满了 但是没有大文件   解决思路: 1、用df 检查发现/根目录可用空间为0 [root@/]#df -h 2、用du检查发现各目录占用的空间都很少,有约3G的空间莫名其妙地丢了. [root@/]# du -m –max-depth=1|sort -gr 3、用lsof检查后才发现原因是,有文件被删除,而进程还活着...

不同linux禁用nouveau驱动方法

不同Linux系统nouveau驱动禁用方式 Fedora 创建文件/usr/lib/modprobe.d/blacklist-nouveau.conf,添加如下文本: blacklist nouveau options nouveau modeset=0 重新生成initramfs。 $ sudo dracut --force RHEL/Cent...

mongo部署(linux)

Linux版本:CentOS release 6.9 Mongodb版本:mongodb-linux-x86_64-3.6.1.tgz 1、解压文件 执行解压命令:tar -zxvf mongodb-linux-x86_64-3.6.1.tgz   2、创建数据,日志目录 命令:mkdir /my/mydata/mongodb       mkdir /m...

Linux学习笔记(17)Linux防火墙配置详解

目录 【1】简单实例【1.1】查看修改目前防火墙状态 【2】实例分析 【2.1】基本释义 【2.2】最佳实践案例 【2.3】防火墙常用命令 【3】Centos7常用操作 【4】其他参考 回到顶部 【1】简单实例 【1.1】查看修改目前防火墙状态 service iptables status 修改防火墙规则   下面的配置是让端...