2020-01-09 18:52:12 one312 阅读数 8
  • 安卓编译与开发、Linux内核及驱动

    安卓编译与开发、Linux内核及驱动视频教程,该课程内容包括一、源码编译:1、常见的ROM种类、谷歌的ROM、第三方的ROM2、区别3、RockChip的ROM、4、编译环境配置、源码下载、编译命令;二、源码开发:源码结构分析、Launcher开发、需求分析、系统级应用;三、内核讲解:内核用途、内核结构、内核职能、内核源码编译、驱动开发;四、内核开发:1、体系架构、目录结构、中断机制、内核进程控制、2、内核库文件、例子简单分析、3、内核调度流程4、内核组件工具 嘉宾介绍:仝利,英文名Burning,CSDN博客讲师,多年主要从事于流媒体,网络通讯,p2p等技术的开发与研究。目前在创业,产品是面向企业会议室和家庭客厅的多媒体通讯盒子的开发。国内还没有相关产品,预计产品会在8月份上市。

    9150 人正在学习 去看看 CSDN讲师

linux的启动流程

1.加载内核。操作系统接管硬件以后,首先读入/boot目录下的内核文件。

2.启动初始化进程。内核文件加载以后,就开始运行第一个程序/sbin/init,它的作用是初始化系统环境。

3.确定运行级别。许多程序需要开机启动,他们在Windows叫做“”服务“”(Service),在linux叫做“”“守护进程”(deamon)。

  init进程的主要任务就是运行这些开机启动程序。Linux允许不同场合分配不同的开机启动程序,这叫做“运行级别”(runlevel)。

  也就是说,启动是根据“”运行级别“确定要运行那些程序”。

Linux 7个运行级别(0:关机,停机模式、1:单用户模式、2:多用户模式、3:完整的多用户文本模式、4:系统未使用,保留一般不用、5:图形化模式、6:重启模式),运行级就是操作系统当前正在运行的功能级别。这个级别从0到6 ,具有不同的功能。


级别具体说明:

0: 系统停机(关机)模式,系统默认运行级别不能设置为0,否则不能正常启动,一开机就自动关机。
1:单用户模式,root权限,用于系统维护,禁止远程登陆,就像Windows下的安全模式登录。
2:多用户模式,没有NFS网络支持。
3:完整的多用户文本模式,有NFS,登陆后进入控制台命令行模式。
4:系统未使用,保留一般不用,在一些特殊情况下可以用它来做一些事情。例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置。
5:图形化模式,登陆后进入图形GUI模式或GNOME、KDE图形化界面,如X Window系统。
6:重启模式,默认运行级别不能设为6,否则不能正常启动,就会一直开机重启开机重启。

4.加载开机启动程序。七种预设的"运行级别"各自有一个目录,存放需要开机启动的程序。不难想到,如果多个"运行级别"需要启动同一个程序,那么这个程序的启动脚本,就会在每一个目录里都有一个拷贝。这样会造成管理上的困扰:如果要修改启动脚本,岂不是每个目录都要改一遍?

Linux的解决办法,就是七个 /etc/rcN.d 目录里列出的程序,都设为链接文件,指向另外一个目录 /etc/init.d ,真正的启动脚本都统一放在这个目录中。init进程逐一加载开机启动程序,其实就是运行这个目录里的启动脚本。

5.用户登录。

(1)命令行登录:init进程调用getty程序(意为get teletype),让用户输入用户名和密码。输入完成后,再调用login程序,核对密码(Debian还会再多运行一个身份核对程序/etc/pam.d/login)。如果密码正确,就从文件 /etc/passwd 读取该用户指定的shell,然后启动这个shell。

(2)ssh登录:这时系统调用sshd程序(Debian还会再运行/etc/pam.d/ssh ),取代getty和login,然后启动shell。

(3)图形界面登录:init进程调用显示管理器,Gnome图形界面对应的显示管理器为gdm(GNOME Display Manager),然后用户输入用户名和密码。如果密码正确,就读取/etc/gdm3/Xsession,启动用户的会话。

6.进入 login shell。所谓shell,简单说就是命令行界面,让用户可以直接与操作系统对话。用户登录时打开的shell,就叫做login shell。Debian默认的shell是Bash,它会读入一系列的配置文件。上一步的三种情况,在这一步的处理,也存在差异。

(1)命令行登录:首先读入 /etc/profile,这是对所有用户都有效的配置;然后依次寻找下面三个文件,这是针对当前用户的配    置。

~/.bash_profile
~/.bash_login
~/.profile

     需要注意的是,这三个文件只要有一个存在,就不再读入后面的文件了。比如,要是 ~/.bash_profile 存在,就不会再读入后面两个文件了。

(2)ssh登录:与第一种情况完全相同。

(3)图形界面登录:只加载 /etc/profile 和 ~/.profile。也就是说,~/.bash_profile 不管有没有,都不会运行。

7.打开 non-login shell。用户进入操作系统以后,常常会再手动开启一个shell。这个shell就叫做 non-login shell,意思是它不同于登录时出现的那个shell,不读取/etc/profile和.profile等配置文件。

non-login shell的重要性,不仅在于它是用户最常接触的那个shell,还在于它会读入用户自己的bash配置文件 ~/.bashrc。大多数时候,我们对于bash的定制,都是写在这个文件里面的。

8.下面是整个过程的简图。

9.参考链接:

http://www.ruanyifeng.com/blog/2013/08/linux_boot_process.html

https://www.cnblogs.com/ljs05/p/7325920.html

 

2015-07-22 17:22:50 xdshengk 阅读数 645
  • 安卓编译与开发、Linux内核及驱动

    安卓编译与开发、Linux内核及驱动视频教程,该课程内容包括一、源码编译:1、常见的ROM种类、谷歌的ROM、第三方的ROM2、区别3、RockChip的ROM、4、编译环境配置、源码下载、编译命令;二、源码开发:源码结构分析、Launcher开发、需求分析、系统级应用;三、内核讲解:内核用途、内核结构、内核职能、内核源码编译、驱动开发;四、内核开发:1、体系架构、目录结构、中断机制、内核进程控制、2、内核库文件、例子简单分析、3、内核调度流程4、内核组件工具 嘉宾介绍:仝利,英文名Burning,CSDN博客讲师,多年主要从事于流媒体,网络通讯,p2p等技术的开发与研究。目前在创业,产品是面向企业会议室和家庭客厅的多媒体通讯盒子的开发。国内还没有相关产品,预计产品会在8月份上市。

    9150 人正在学习 去看看 CSDN讲师

还是拿TQ210的板子做例子吧

1.修改内核代码,增加一个USER1分区(),0x8000000就是128M的地址,待会准备在这个分区烧写一个linux 内核,实现从这个分区启动

static struct mtd_partition tq210_partition_info[] = {
 [0] = {
  .name  = "Bootloader",
  .offset  = 0,
  .size  = 0x200000,
  .mask_flags = MTD_CAP_NANDFLASH,
 },
/* [1] = {
  .name  = "Param",
  .offset  = 0x80000,
  .size  = 0x80000,
  .mask_flags = MTD_CAP_NANDFLASH,
 },*/
 [1] = {
  .name  = "LOGO",
  .offset  = 0x200000,
  .size  = 0x300000,
  .mask_flags = MTD_CAP_NANDFLASH,
 },
 [2] = {
  .name  = "Kernel",
  .offset  = 0x500000,
  .size  = 0x500000,
  .mask_flags = MTD_CAP_NANDFLASH,
 },
 [3] = {
  .name  = "ROOTFS",
  .offset  = 0xA00000,
  .size  = 0x6400000,
 },
[4] = {
  .name  = "USER1",
  .offset  = 0x8000000,
  .size  = MTDPART_SIZ_FULL,
 },
};

2.下载mtd-utils-1.5.1,编译,

下载地址:http://download.csdn.net/detail/xdshengk/8923849

   首先打开common.mk,增加CROSS=arm-linux-

  然后打开Makefile,将下面的参数打开,或者执行make  WITHOUT_XATTR=1

#ifeq ($(WITHOUT_XATTR), 1)
  CPPFLAGS += -DWITHOUT_XATTR
#endif

3.启动系统,格式化分区

[root@EmbedSky /]# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00200000 00020000 "Bootloader"
mtd1: 00300000 00020000 "LOGO"
mtd2: 00500000 00020000 "Kernel"
mtd3: 06400000 00020000 "ROOTFS"
mtd4: 18000000 00020000 "USER1"

确认分区为mtd4(字符型),mtdblock4为块设备

格式化6m空间,就够内核用了

首先看一下使用方法:

[root@EmbedSky arm-linux]# ./flash_erase --help
Usage: flash_erase [options] MTD_DEVICE <start offset> <block count>
Erase blocks of the specified MTD device.
Specify a count of 0 to erase to end of device.

  -j, --jffs2       format the device for jffs2
  -N, --noskipbad   don't skip bad blocks
  -u, --unlock      unlock sectors before erasing
  -q, --quiet       do not display progress messages
      --silent      same as --quiet
      --help        display this help and exit
      --version     output version information and exit

 

做个擦写测试:
[root@EmbedSky arm-linux]# ./flash_erase /dev/mtd4 0 1
Erasing 128 Kibyte @ 0 -- 100 % complete
[root@EmbedSky arm-linux]# ./flash_erase /dev/mtd4 0 2
Erasing 128 Kibyte @ 20000 -- 100 % complete
[root@EmbedSky arm-linux]# ./flash_erase /dev/mtd4 0 3
Erasing 128 Kibyte @ 40000 -- 100 % complete
[root@EmbedSky arm-linux]# ./flash_erase /dev/mtd4 0 4
Erasing 128 Kibyte @ 60000 -- 100 % complete

经过了测试,发现一个block为0x20000大小,也就是128k,所以擦写50个块,6.25m就够了

[root@EmbedSky arm-linux]# ./flash_erase /dev/mtd4 0 50
Erasing 128 Kibyte @ 620000 -- 100 % complete

然后烧写内核,-p是使页对齐

[root@EmbedSky arm-linux]# ./nandwrite -p /dev/mtd4 /home/zImage
Writing data to block 0 at offset 0x0
Writing data to block 1 at offset 0x20000
Writing data to block 2 at offset 0x40000
Writing data to block 3 at offset 0x60000
Writing data to block 4 at offset 0x80000
Writing data to block 5 at offset 0xa0000
Writing data to block 6 at offset 0xc0000
Writing data to block 7 at offset 0xe0000
Writing data to block 8 at offset 0x100000
Writing data to block 9 at offset 0x120000
Writing data to block 10 at offset 0x140000
Writing data to block 11 at offset 0x160000
Writing data to block 12 at offset 0x180000
Writing data to block 13 at offset 0x1a0000
Writing data to block 14 at offset 0x1c0000
Writing data to block 15 at offset 0x1e0000
Writing data to block 16 at offset 0x200000
Writing data to block 17 at offset 0x220000
Writing data to block 18 at offset 0x240000
Writing data to block 19 at offset 0x260000
Writing data to block 20 at offset 0x280000
Writing data to block 21 at offset 0x2a0000
Writing data to block 22 at offset 0x2c0000
Writing data to block 23 at offset 0x2e0000
Writing data to block 24 at offset 0x300000
Writing data to block 25 at offset 0x320000
Writing data to block 26 at offset 0x340000
Writing data to block 27 at offset 0x360000
Writing data to block 28 at offset 0x380000
Writing data to block 29 at offset 0x3a0000
Writing data to block 30 at offset 0x3c0000
Writing data to block 31 at offset 0x3e0000
Writing data to block 32 at offset 0x400000
Writing data to block 33 at offset 0x420000
Writing data to block 34 at offset 0x440000
Writing data to block 35 at offset 0x460000
Writing data to block 36 at offset 0x480000
Writing data to block 37 at offset 0x4a0000
Writing data to block 38 at offset 0x4c0000
[root@EmbedSky arm-linux]#

4,修改启动参数,让uboot从128M的地方启动内核


netmask=255.255.255.0
lcdtype=X800Y480
bootargs_defaults=setenv bootargs ${bootargs} lcd=${lcdtype}
bootloaderimgname=u-boot.bin
logoimgname=logo.bin
nkimgname=NK.bin
kernelimgname=zImage.bin
rootimgname=root.bin
mtdids=nand0=s5pv210-nand
mtdparts=mtdparts=s5pv210-nand:1m@0(bios),1m(params),3m(logo),5m(kernel),-(root)
nfsserverip=192.168.1.8
nfsipaddr=192.168.1.5
nfsnetmask=255.255.255.0
nfs_dir=/dirnfs
bootargs=noinitrd init=/init console=ttySAC0 root=/dev/nfs rootwait=1 nfsroot=192.168.1.8:/dirnfs ip=192.168.1.5:192.168.1.8:192.168.1.5:255.255.255.0:www.embedsky.com:eth0:off
stdin=serial
stdout=serial
stderr=serial
partition=nand0,0
mtddevnum=0
mtddevname=bios

Environment size: 846/16380 bytes

##### Parameter Menu #####
[1] Set NFS boot parameter
[2] Set Yaffs boot parameter for Android or Standard Linux
[3] Set UBIfs boot parameter for Android or Standard Linux
[4] Set parameter
[5] View the parameters
[c] Choice lcd type.
[d] Delete parameter
[i] Display nand flash infomation.
[s] Save the parameters to Nand Flash
[q] Return main Menu
Enter your selection: 4
Name: *mtdparts
Value: *mtdparts=s5pv210-nand:1m@0(bios),1m(params),126m(logo),5m(kernel),-(root)

保存,启动成功

[u] Download bootloader to SD Card
Enter your selection: 8
Start Linux ...

NAND read: device 0 offset 0x8000000, size 0x500000


 5242880 bytes read: OK
Boot with zImage

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Initializing cgroup subsys cpu
Linux version 3.0.8-EmbedSky (root@ubuntu) (gcc version 4.4.6 (for TQ210 EmbedSky Tech) ) #17 PREEMPT Tue Jul 21 20:04:41 PDT 2015
CPU: ARMv7 Processor [412fc082] revision 2 (ARMv7), cr=10c53c7f
CPU: VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: TQ210
Truncating RAM at 40000000-5fffffff to -54ffffff (vmalloc region overlap).
Memory policy: ECC disabled, Data cache writeback
bootargs no set lcd type! using default a70.
CPU S5PV210/S5PC110 (id 0x43110220)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S5PV210: PLL settings, A=1000000000, M=667000000, E=80000000 V=54000000
S5PV210: ARMCLK=1000000000, HCLKM=200000000, HCLKD=166750000

 

 


2011-03-25 22:09:00 icyrat 阅读数 10248
  • 安卓编译与开发、Linux内核及驱动

    安卓编译与开发、Linux内核及驱动视频教程,该课程内容包括一、源码编译:1、常见的ROM种类、谷歌的ROM、第三方的ROM2、区别3、RockChip的ROM、4、编译环境配置、源码下载、编译命令;二、源码开发:源码结构分析、Launcher开发、需求分析、系统级应用;三、内核讲解:内核用途、内核结构、内核职能、内核源码编译、驱动开发;四、内核开发:1、体系架构、目录结构、中断机制、内核进程控制、2、内核库文件、例子简单分析、3、内核调度流程4、内核组件工具 嘉宾介绍:仝利,英文名Burning,CSDN博客讲师,多年主要从事于流媒体,网络通讯,p2p等技术的开发与研究。目前在创业,产品是面向企业会议室和家庭客厅的多媒体通讯盒子的开发。国内还没有相关产品,预计产品会在8月份上市。

    9150 人正在学习 去看看 CSDN讲师

制作开机Logo
方法一:
Drivers/video/logo/logo_linux_clut224.ppm是默认的启动Logo图片,把自己的Logo图片(png格式)转换成ppm格式,替换这个文件,同时删除logo_linux_clut224.c logo_linux_clut224.o文件,重新编译
具体方法:
#pngtopnm logo_linux_clut224.png > logo_linux_clut224.pnm
#pnmquant 224 logo_linux_clut224.pnm > logo_linux_clut224.pnm
#pnmtoplainpnm logo_linux_clut224.pnm > logo_linux_clut224.ppm
注:先把png转换成pnm格式,但内核的Logo最高只支持224色,需要把颜色转换成224色,最后把pnm转成ppm,文件名必须是logo_linux_clut224.ppm
方法二:

用RedHat9.0自带的图片编辑工具GIMP(其他发行版自己安装就行了)。

1.将颜色数改为224(在GIMP中一次选择 图像->模式->索引。如下图所示)。

2.调整大小:宽高都小两像素,否则不显示。

3.另存为,保存为ppm格式,在弹出的对话框中选择Ascii,然后复制到Logo文件夹替换原来的文件,同时删除logo_linux_clut224.c logo_linux_clut224.o文件。

最后编译内核:(编译通过)

2011-08-09 22:31:23 mockbird 阅读数 3881
  • 安卓编译与开发、Linux内核及驱动

    安卓编译与开发、Linux内核及驱动视频教程,该课程内容包括一、源码编译:1、常见的ROM种类、谷歌的ROM、第三方的ROM2、区别3、RockChip的ROM、4、编译环境配置、源码下载、编译命令;二、源码开发:源码结构分析、Launcher开发、需求分析、系统级应用;三、内核讲解:内核用途、内核结构、内核职能、内核源码编译、驱动开发;四、内核开发:1、体系架构、目录结构、中断机制、内核进程控制、2、内核库文件、例子简单分析、3、内核调度流程4、内核组件工具 嘉宾介绍:仝利,英文名Burning,CSDN博客讲师,多年主要从事于流媒体,网络通讯,p2p等技术的开发与研究。目前在创业,产品是面向企业会议室和家庭客厅的多媒体通讯盒子的开发。国内还没有相关产品,预计产品会在8月份上市。

    9150 人正在学习 去看看 CSDN讲师

proc文件的实现也需要编写出一个内核模块并插入内核。模块的编写过程我们已经Hello,Module过了,而proc文件的实现稍微复杂一些。

在linux内核模块编写中,常常会有一些结构体,结构体中定义了很多函数指针,内核模块的编写常常是围绕着实现这些函数指针而进行的。实现了这些接口便可以调用相应的函数把相应的功能模块插入内核(拗口),以下是proc文件的结构体接口描述:

//linux/proc_fs.h

//读函数原型
typedef	int (read_proc_t)(char *page, char **start, off_t off,
			  int count, int *eof, void *data);

//写函数原型
typedef	int (write_proc_t)(struct file *file, const char __user *buffer,
			   unsigned long count, void *data);

			   
struct proc_dir_entry {
	unsigned int low_ino;
	unsigned short namelen;
	const char *name;	//proc文件的名字
	mode_t mode;
	nlink_t nlink;
	uid_t uid;
	gid_t gid;
	unsigned long size;
	struct inode_operations * proc_iops;
	struct file_operations * proc_fops;
	get_info_t *get_info;
	struct module *owner;
	struct proc_dir_entry *next, *parent, *subdir;
	void *data;
	read_proc_t *read_proc;			//读函数(需用户实现)
	write_proc_t *write_proc;		//写函数(需用户实现)
	atomic_t count;		/* use count */
	int deleted;		/* delete flag */
};

/*创建一个proc结构体
@name: proc文件的名字
@mode:
@parent: proc文件被创建的目录
*/
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);
/*
从内核中移除一个proc文件
*/
void remove_proc_entry(const char *name, struct proc_dir_entry *parent) ;

已经有一些预定义的proc目录可直接作为parent使用:

proc_dir_entry 在文件系统中的位置
proc_root_fs /proc
proc_net /proc/net
proc_bus /proc/bus
proc_root_driver /proc/driver

write_proc_t 函数(写函数):用户空间到内核空间

很明显,write_proc_t函数的实现赋予proc 写语义,它的原型如下:

int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data);

参数file可忽略,buffer为用户空间需要写入的数据的头指针,count 为用户空间需要写入内核的数据长度,data为proc结构体得私有数据,对应于 struct  proc_dir_entry结构体中的data字段。编码过程中常常需要将用户空间的数据拷贝到内核,因为用户空间的指针不能在内核空间中使用(那不是很多拷贝,效率不是很低..),常见的拷贝函数有以下两枚

/* Copy buffer to user-space from kernel-space */
unsigned long copy_to_user( void __user *to, const void *from,unsigned long n );
/* Copy buffer to kernel-space from user-space */
unsigned long copy_from_user( void *to,const void __user *from, unsigned long n );


__user宏只是方便源代码查找而已,没有实际语义。这两个copy函数可能会造成阻塞,故只能在进程上下文中使用,如果在中断上下文中使用,那恭喜你,你的内核会莫名的挂掉了。

read_proc_t 函数(读函数):内核空间到用户空间
typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data);
当某个进程读取我们的proc文件时,内核会分配一个内存页(即PAGE_SIZE大小的内存块),内核模块将数据写入到这张页来返回数据到用户空间。
以上参数中,page参数是为进程分配的内存页,其中count定义了定义了可以写入的最大字符数。在返回多页数据(通常一页是4K),我们需要使用start和off参数。当所有数据全部写入后,就需要设置eof(文件结束参数)。与write类似,data也是私有数据。此处提供的page缓冲区在内核空间。因此不必使用copy_to_user,而可以直接写入。该函数返回写入的字节数。

start参数:start参数用户实现返回大于一页的数据。在read_proc_t方法被调用时,*start的初始值为NULL。如果保留*start为NULL,内核将家丁数据保存在内存页偏移量0的地方,并且忽略off参数。相反,如果我们将*start设为非空值,内核将认为由*start指向的数据是off参数指定的偏移量中的数据。通常返回少量数据的简单read_proc函数可忽略start参数,复杂的read_proc函数将*start设置为页面,并将请求偏移量处得数据放到内存页。
start参数还有另一种用法,将在下文继续讨论。

以下内容实现一个简单的可读写的proc文件例子:  

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/proc_fs.h>
#include<linux/string.h>
#include<linux/vmalloc.h>
#include<asm/uaccess.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Fortune Cookie Kernel Module");


#define MAX_COOKIE_LENGTH	 PAGE_SIZE

//保存proc结构体指针
static struct proc_dir_entry *proc_entry;

//保存缓冲区指针
static char *cookie_pot;

// cookie_index=已经写入的数据数目-1 。
static int cookie_index;  
//遍历标
static int next_fortune;


ssize_t fortune_write(struct file *filp,const char __user *buff, 
			unsigned long len, void *data)
{
	int space_avaliable=( MAX_COOKIE_LENGTH - cookie_index) +1;	 //计算剩余空间
	if(len>space_avaliable)
	{
		printk(KERN_INFO "fortune:cookie pot is full\n");
		return -ENOSPC;
	}
	
	if(copy_from_user(&cookie_pot[cookie_index],buff,len  ) )
		return -EFAULT;
	
	cookie_index+=len;
	cookie_pot[cookie_index-1]=0;
	return len;
}

//每读一次返回一个之前写入的字符串。
int fortune_read(char *page,char **start,off_t off,
				int count ,int *eof,void *data)
{
	int len;
	printk(KERN_INFO "fortune_read\n");
	if(off>0)
	{	
		*eof=1;		
		return 0;
	}
	
	if( next_fortune >= cookie_index ) next_fortune= 0 ;
	len=sprintf(page,"%s\n", &cookie_pot[ next_fortune ] ) ;
	next_fortune+=len;
	
	return len;
	
}

int init_fortune_module(void)
{
	int ret=0;
	//分配一个页大小的数据块,用cookie_pot保存
	cookie_pot=(char *)vmalloc( MAX_COOKIE_LENGTH );
	if(!cookie_pot)
		ret=-ENOMEM;		//错误处理。显然
	else
	{
		memset(cookie_pot,0,MAX_COOKIE_LENGTH);	//清零
		proc_entry=create_proc_entry("fortune",0644,NULL);		//创建一个新的proc文件,名为fortune.
		if(proc_entry==NULL)
		{
			ret=-ENOMEM;
			vfree(cookie_pot);
			printk(KERN_INFO "fortune :couldn't create proc entry\n");
		}
		else
		{
			cookie_index=0;
			next_fortune=0;
			proc_entry->read_proc=fortune_read;
			proc_entry->write_proc=fortune_write;
			proc_entry->owner=THIS_MODULE;
			printk(KERN_INFO "fortune: Module load.\n");		//一些一本的proc结构体初始化而已。
		}
	}
	return ret;
}

void cleanup_fortune_module(void)
{
	remove_proc_entry("fortune",proc_entry);		//移除
	vfree( cookie_pot );
	printk(KERN_INFO "fortune:Module unload\n");
}

module_init(init_fortune_module);
module_exit(cleanup_fortune_module);


上文实现了一个可以读写的proc文件。读者可以往/proc/fortune中写入字符串后再读取来查看该模块的行为。







2018-11-13 21:54:26 wh_0727 阅读数 151
  • 安卓编译与开发、Linux内核及驱动

    安卓编译与开发、Linux内核及驱动视频教程,该课程内容包括一、源码编译:1、常见的ROM种类、谷歌的ROM、第三方的ROM2、区别3、RockChip的ROM、4、编译环境配置、源码下载、编译命令;二、源码开发:源码结构分析、Launcher开发、需求分析、系统级应用;三、内核讲解:内核用途、内核结构、内核职能、内核源码编译、驱动开发;四、内核开发:1、体系架构、目录结构、中断机制、内核进程控制、2、内核库文件、例子简单分析、3、内核调度流程4、内核组件工具 嘉宾介绍:仝利,英文名Burning,CSDN博客讲师,多年主要从事于流媒体,网络通讯,p2p等技术的开发与研究。目前在创业,产品是面向企业会议室和家庭客厅的多媒体通讯盒子的开发。国内还没有相关产品,预计产品会在8月份上市。

    9150 人正在学习 去看看 CSDN讲师

1.Linux下文件操作函数:
 

系统调用函数:open   read  write  close   lseek   stat

库函数:fopen   fread  fwrite  fclose   flseek

 

FILE *fopen(char *file,char *flag);          

int open(char *file,int flag,/*int mode*/)      注:   

int read(int fd,void* buff,int size)  

       注:size表示一次最多读取几个字节,缓冲区大小

       若返回值为-1,即操作出错,否则返回读取到的字节数

int write(int fd,void* buff,int size))

      buff:要写入到文件中的数据起始位置

     size:写入的个数,数据的长度

int close(int fd)    关闭文件描述符

int sleek(int fd,int count,int flag)    移动读写偏移量

    count:移动的字节数

    flag:移动的起始位置

2.以open为例,用户态到内核态的切换

没有更多推荐了,返回首页