第四步 Linux初步学习内核
来源:互联网 发布:网络直播紫菱真实姓名 编辑:程序博客网 时间:2024/05/16 15:09
局域网络共享:http://blog.sina.com.cn/s/blog_7a85b6e70100ri7a.html
虚拟机网络设置:http://blog.sina.com.cn/s/blog_601bc5cf0101d32z.html
help:帮助
printenv:查看环境变量
setenv: 添加、修改、删除环境变量
setenv filename test.txt 添加变量filename
setenv filename hello.txt 修改环境变量值为hello.txt
setenv filename 删除环境变量filenames
saveenv : 保存环境变量
tftp通过网络下载文件(注意:使用tftp,需先配置好网络)
setenv ethaddr xx:xx....
setenv ipaddr xx.xx.xx.xx
setenv serverip xx.xx.xx.xx(tftp服务器地址)(Linux的IP地址)
ping 服务器地址 (xx is alive 说明成功)
vim /etc/xinetd.d/tftp 修改配置(disable=no)
service tftp restart
setenforce 0
文件下载范例:
tftp 0x50008000 uImage.bin
(把tftp服务器的uImage.bin下载到0x50008000处)
bootm {addr} {arg} 执行固定格式的二进制程序
bootm 0x50008000
md addr内存显示(md.b)
mm addr 内存修改命令
nand erase 0x40000000 0x50000000(擦除nand flash 从0x4... 到0x5..的内容)
nand write 内存起始地址 flash起始地址 长度 (写nand flash)
nand read 内存起始地址 flash起始地址 长度
例:nand write 0xc0008000 0x400000 500000
设置自启动:
1.设置从nand flash启动(设置后保存)
setenv bootcmd nand read c0008000 400000 500000 \; bootm c0008000
2.设置自动下载内核到内存后启动
setenv tftp c0008000 uImage.bin \; bootm c0008000
Linux体系结构:
1.user space:用户程序和C库(硬盘、flash中)
2.kernel space:系统调用接口、内核代码等(内存中)
CPU不同工作模式权限不一样,通过系统调用和硬件中断能够
完成从用户空间到内核空间的切换
Linux内核架构:7模块
system call interforce(SCI)
process management(PM)
memory management(MM)
arch
virtual file System (VFS)
Network Stack
Device Drivers(DD)
目录结构:
arch目录:结构体系相关代码
documentation:内核的文档
drivers:驱动
fs:文件系统
net:网络协议实现代码
下载内核源代码:www.kernel.org
下载系统到开发板所须文件: bootloader、内核映象、文件印象
一.Linux内核配置方法:
make config:基于文本模式的交互式配置
make menuconfig:基于文本模式的菜单型配置(redhat下出错
可能没安装包ncurses devel)
[*] : 内核映象 (必要功能)直接加入内存运行
<M> : 内核模块 (偶尔调用的功能)需要时才加入内存里面运行
< > : 不选择该功能
二.内核编译:
1.编译内核([*]部分) [1]. make zImage [2]. make bzImage V=1
2.编译内核模块(<M>部分)
1>. make modules (编译、时间很长)
2>. make modules_install
3.制作init ramdisk(打包)
方法:mkinitrd initrd-$version $version
$servion可以通过查询/lib/modules下的目录得到(uname -r)
例:mkinitrd initrd-2.6.39 2.6.39
三.安装内核:复制内核文件到/boot/
1.cp linux-2.6.39/arch/x86/boot/bzImage /boot/vmlinuz-$version
2. cp initrd-$version /boot/
3. 修改/etc/grub.conf (系统启动时的选项)
文件最后几行 (title Red Hat...开始)
复制,改所有的2.6.32.xxx(原版本)为2.6.39(新版本)
4.重启Linux
四.清理内核: make clean(只清理*.o文件)
make distclean (清除*.o和.config文件)
下载内核到开发板:
1.make distclean
2.配置内核 make menuconfig ARCH=arm
3.编译内核 make uImage ARCH=arm CROSS_COMPILE=arm-linux-
(若报错拷贝u-boot/tools/mkimage到/bin/)
4.下载u-boot.bin
根文件系统创建:
1.创建目录 mkdir rootfs
cd rootfs
mkdir bin dev lib proc sbin ysy usr mnt tmp var
mkdir usr/bin usr/sbin lib/modues
1.2 创建设备文件
cd /rootfs/dev
mknod -m 666 console c 5 1
mknod -m 666 null c 1 3
1.3 加入配置文件
tar etc.tar.gz
mv etc/* .../rootfs/etc -rf
1.4 添加内核模块
cd .../linux(内核文件目录,之前复制好的)
make modules ARCH=arm CROSS_COMPILE=arm-linux-
make modules_install ARCH=arm INSTALL_MOD_PATH=.../rootfs
(编译在rootfs/lib/module)
1.5 安装busybox
1.配置busybox make menuconfig
busybox settings -> build options ->
选中“build busybox as a static binary”静态链接
cross compiler prefix (arm-linux-)
installation options->
选中"don't use/usr"
选中该项可以避免busybox被安装到宿主系统的/usr目录下,破坏宿主系统
busybox installation prefix(/xxxx/rootfs)
该选项表明编译后的busybox的安装位置
2.编译busybox
make
uImage中包含内核和文件系统压缩包两部分
挂载根文件系统:(根据硬件和系统需求决定)
1.文件系统类型
1.基于Nandflash的文件系统 (1)Yaffs2 (2)UbiFS(读)
2.基于NorFlash的文件系统 Jffs2 (可读可写)
3.基于内存的文件系统(1)Ramdisk (2)Initramfs(启动速度快)
4基于网络的文件系统 NFS (用于开发阶段)
2.使用Initramfs挂载文件系统
1.cd ..../rootfs/
ln -s ./bin/busybox init
2.配置Linux内核,支持initramfs
cd ../../linux(内核文件夹)
make menuconfig ARCH=arm
(找到initial RAM filesysten...改路径为../rootfs)
3.重新编译内核
make uImage ARCH=arm CROSS_COMPILE=arm-linux-
4.设置环境变量
setenv bootargs noinitrd console=ttySAC0,115200
5.下载uImage到开发板
2.使用NFS挂载文件系统(添加更改文件不需重新下载)
1.重新配置内核 make menuconfig
1.取消initial RAM filesysten...
2.找到filesystem -> network file system ->
选中root file system on NFS
3.编译make menuconfig ARCH=arm
2.参数配置
setenv bootargs noinitrd
console=ttySAC0,115200 init=/init
root=/dev/nfs rw
nfsroot=192.168.1.3(linux IP):/...../rootfs
ip=192.168.1.6(开发板IP):192.168.1.3(linux IP):
192.168.1.1(网关):255.255.255.0(掩码)::eth0:off
3.下载内核 tftp c0008000 uImage
4.重启 bootm c0008000
内核模块本身并不被编译进内核文件(zImage或bzImage)
根据需要动态的安装和卸载
安装: insmod /home/dnw_usb.ko
卸载: rmmod dnw_usb
查看: lsmod(查看系统中所有的内核模块)
内核代码:头文件:linux/init.h linux/module.h
加载函数:module_init(xx);(入口)
卸载函数:module_exit(xx);
内核printk打印级别:
http://www.educity.cn/linux/1582745.html
Makefile编写思路:
1.指明所编译内核模块最终生成文件
2.内核代码路径
3.目标 :编译内核模块命令
复制编译后*.ko文件到rootfs目录(tftp下载)下载
imsmod安装
模块申明:
MODULE_LICENSE("遵守的协议")
申明改模块遵守的许可证协议,如:"GPL","GPL v2"等
MODULE_AUTHOR("作者")
MODULE_DESCRIPTION("模块功能描述")
MODULE_VERSION("V1.0")
模块参数:用于在加载模块是传递参数给模块
宏 module_param(name,type,perm)
name: 变量名称
type:变量类型,bool:布尔型int:整形charp:字符串行
perm:访问权限 S_TRUGO读权限 S_IWUSR写权限
例:
int a=1;
char *st;
module_param(a,int,S_IRUGO);
module_param(st,charp,S_IRUGO);
内核符号导出:
EXPORT_SYMBOL(符号名)符号可为函数名、变量名等
EXPORT_SYMBOL_GPL(符号名)(只用于包含GPL许可证模块)
linux内存管理子系统:1.物理内存分配 2.地址映射
虚拟地址映射:(转换过程:页目录+页表过度)
固定映射的线性地址区、(寄存器等)
永久内核映射区
vmalloc区、(固定访问高级内存区)
直接映射区(虚拟地址=3G+物理地址)
物理内存分配:(只有访问虚拟地址时才分配实在的内存)
进程管理子系统:
程序:存放在磁盘上的一系列代码和数据的可执行映像,是一个静止的实体
进程:是一个执行中的程序,他是动态的实体
进程四要素:
1.有一段程序供执行
2.专用的内核空间栈
3.有一个task_struct数据结构(进程控制块)用于接受内核调用
4.有独立的用户空间
(用户线程:只有共享空间,内核线程:共享用户空间都没有)
进程状态:
1.TASK_RUNNING 就绪态(进程刚被创建时)
2.TASK_INTERRUPTIBLE 阻塞态(等待条件成熟)
3.TASK_UNINTERRUPTIBLE 阻塞态(不可由其他信号或中断唤醒)
4.TASK_KILLABLE Linux进入新的睡眠状态(可被SIGKILL唤醒)
5.TASK_TRACED 正在被调试状态
6.TASK_DEAD 进程退出状态(调用do_exit)
进程描述:
在Linux内核代码中,线程、进程都是用结构task_struct(sched.h)
来表示,它包含大量描述进程、线程的信息,比较重要的有:
pid_t pid;(进程号)long state (进程状态)int prio(优先级)
进程调度:
1.调度策略:SCHED_FIFO陷入先出实时进程
SCHED_RR时间片轮转实时进程
SCHED_NORMAL(SCHED_OTHER)普通分时进程
SCHED_BATCH批处理进程
SCHED_IDLE只有在系统空闲才被调用的进程
2.调度时机:(schedule()函数什么时候被调用)
主动式:内核中直接调用schedule,当进程需要等待资源而暂停运行时
会把自己的状态置于挂起(睡眠),并主动请求调度,让出CPU
范例: current->state=TASK_INTERRUPTIBLE;
schedule();
被动式:抢占式调度(分用户态抢占和内核态抢占)
用户态:从系统调用返回用户空间或中断处理程序返回时
(内核即将返回用户空间时,如果need_resched标志被设置
会导致schedule被调用,发生用户抢占),当某个进程耗尽时间片时,
或者当一个优先级更高的进程进入可执行态的时候,会设置need_resched
内核态抢占:中断处理程序完成,返回内核空间
获取信号量再释放信号量等如解锁
在支持内核抢占的系统中,某些特例下是不允许抢占的:
v 内核正在运行中断处理。
v 内核正在进行中断上下文的Bottom Half(中断的底半部)处理。
硬件中断返回前会执行软中断,此时仍然处于中断上下文中。
v 进程正持有spinlock自旋锁、writelock/readlock读写锁等,
当持有这些锁时,不应该被抢占,否则由于抢占将可能导致其
他进程长期得不到锁,而让系统处于死锁状态。
v 内核正在执行调度程序Scheduler。抢占的原因就是为了进行
新的调度,没有理由将调度程序抢占掉再运行调度程序。
调度时机-抢占计数:
为保证Linux内核在以上情况下不会被抢占,抢占式内核使用了一个变量
preempt_count,称为内核抢占计数。这一变量被设置在进程的thread_info
结构中。每当内核要进入以上几种状态时,变量中。每当内核要进入以上几种状
态时,变量preempt_count就加1,指示内核不允许抢占。每当内核从以上几种状
态退出时,变量preempt_count就减1,同时进行可抢占的
判断与调度。
调度步骤 :
Schedule函数工作流程如下:
1). 清理当前运行中的进程;
2). 选择下一个要运行的进程;
3). 设置新进程的运行环境;
4). 进程上下文切换 。
内核链表:(双向循环链表)
传统链表:指针指向节点的数据域
内核链表:指针指向节点指针域
内核链表-结构:
struct list_head
{
struct list_head *next, *prev;
};
内核链表-函数:(使用参考已有内核代码)
1. INIT_LIST_HEAD:创建链表
2. list_add:在链表头插入节点
3. list_add_tail:在链表尾插入节点
4. list_del
4. list_del:删除节点
5. list_entry:取出节点
6. list_for_each:遍历链表
系统调用:用户程序通过触发软中断,通过swi变量调用内核中相应函数
添加新的系统调用:
kernel/printk.c中写入自己的函数
arch/arm/include/asm/unistd.h添加新编号
arch/arm/kernel/call.S最后中添加新标号
编译内核make uImage ARCH=arm CROSS_COMPILE=arm-Linux-
编写应用代码调用新添加的函数
如:
void pk()
{
__asm__ (
"ldr r7,=363 \n"
"swi \n"
:
:
:"memory");
}
void main()
{
pk();
}
- 第四步 Linux初步学习内核
- linux内核学习初步
- 学习View第四步
- 内核初步学习
- linux内核第四记
- 0K6410学习之初步移植linux内核
- linux驱动学习--第五天:第四章 Linux 内核模块 之 Linux 内核模块简介
- linux驱动学习--第六天:第四章 Linux 内核模块 之 Linux 内核模块编译
- 学习的第四步:学会谦卑
- Lucene4.9基础学习第四步
- 初步了解Linux内核 (1)
- 初步了解Linux内核 (2)
- 初步了解Linux内核 (3)
- Linux内核探讨-- 第四章
- 第四章 Linux内核模块
- 第四章 Linux内核模块
- 第四章 初步进入linux世界
- 第四章 初步进入linux世界
- 关于JAVA、 JAVA Web项目导入数据库驱动包的问题
- osi参考模型
- 类加载器和双亲委派机制
- ios学习--iphone NSURLRequest NSMutableURLRequest 数据请求相关
- 常用的shell脚本
- 第四步 Linux初步学习内核
- android studio各种版本下载
- APK加固之类抽取分析与修复
- Android网络编程框架推荐-Volley
- 突破select的FD_SETSIZE限制
- OpenCV坐标体系的初步认识
- (经典)详解WINDOWS映像劫持技术
- 使用JMeter进行基本压力测试
- Zend Studio 配色方案插件