linux的bmp代码

linux的bmp代码
linux的bmp代码

//////////////////////////////////////////////////bmp.c///////////////////////////////////////////// //////////////////////////////////

/*

fbv -- simple image viewer for the linuxframebuffer

Copyright (C) 2002 Tomasz Sterna

This program is free software; you can redistribute it and/or modify

it under the terms of the GNU General Public License as published by

the Free Software Foundation; either version 2 of the License, or

(at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "config.h"

#ifdef FBV_SUPPORT_BMP

#include "fbv.h"

#include

#include

#include

#include

#define BMP_TORASTER_OFFSET 10

#define BMP_SIZE_OFFSET 18

#define BMP_BPP_OFFSET 28

#define BMP_RLE_OFFSET 30

#define BMP_COLOR_OFFSET54

#define fill4B(a) ( ( 4 - ( (a) % 4 ) ) & 0x03)

struct color {

unsigned char red;

unsigned char green;

unsigned char blue;

};

intfh_bmp_id(char *name)//读取位图头信息,判断是否为"BM"

intfd;

char id[2];

fd = open(name, O_RDONLY);//打开文件

if (fd == -1) {

return(0);

}

read(fd, id, 2);

close(fd);

if ( id[0]=='B' && id[1]=='M' ) {

return(1);

}

return(0);

}

void fetch_pallete(intfd, struct color pallete[], int count)//获取调色板信息

{

unsigned char buff[4];

int i;

lseek(fd, BMP_COLOR_OFFSET, SEEK_SET);//fd,28,SEEK_SET:参数28为新的读写位置

for (i=0; i

read(fd, buff, 4);//将fd所指向的文件的4个字节传送给缓冲区(指针)buff所指内存中

pallete[i].red = buff[2];

pallete[i].green = buff[1];

pallete[i].blue = buff[0];

}

return;

}

intfh_bmp_load(char *name,unsigned char *buffer, unsigned char **alpha, intx,int y)

{

#if 1

intfd, bpp, raster, i, j, k, skip;

unsigned char buff[4];

unsigned char *wr_buffer = buffer + x*(y-1)*3;

struct color pallete[256];

fd = open(name, O_RDONLY);

if (fd == -1) {

return(FH_ERROR_FILE);

}

if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) {//从文件10处开始读写return(FH_ERROR_FORMAT);

}

read(fd, buff, 4);

raster = buff[0] + (buff[1]<<8) + (buff[2]<<16) + (buff[3]<<24);//由上面可知:从bfOffBits

//开始四个字节:每一行扫描的字节数?

if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) {

return(FH_ERROR_FORMAT);

}

read(fd, buff, 2);

bpp = buff[0] + (buff[1]<<8);//可得biBitCount(从28开始2个字节)

switch (bpp){

case 1: /* monochrome 单色*/

skip = fill4B(x/8+(x%8?1:0));

/*#define fill4B(a) ( ( 4 - ( (a) % 4 ) ) & 0x03)

1.BMP文件记录一行图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说,

设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,

这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信息。

2.为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。

如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节

(加1是因为里面有一个像素点要独占了一字节)。如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。

*/

lseek(fd, raster, SEEK_SET);

for (i=0; i

for (j=0; j

read(fd, buff, 1);

for (k=0; k<8; k++) {

if (buff[0] & 0x80) {

*wr_buffer++ = 0xff;

*wr_buffer++ = 0xff;

*wr_buffer++ = 0xff;

} else {

*wr_buffer++ = 0x00;

*wr_buffer++ = 0x00;

*wr_buffer++ = 0x00;

}

buff[0] = buff[0]<<1;

}

}

if (x%8) {

read(fd, buff, 1);

for (k=0; k

if (buff[0] & 0x80) {

*wr_buffer++ = 0xff;

*wr_buffer++ = 0xff;

*wr_buffer++ = 0xff;

} else {

*wr_buffer++ = 0x00;

*wr_buffer++ = 0x00;

*wr_buffer++ = 0x00;

}

buff[0] = buff[0]<<1;

}

}

if (skip) {

read(fd, buff, skip);

}

wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */

}

break;

case 4: /* 4bit palletized */

skip = fill4B(x/2+x%2);//#define fill4B(a) ( ( 4 - ( (a) % 4 ) ) & 0x03) fetch_pallete(fd, pallete, 16);

lseek(fd, raster, SEEK_SET);

for (i=0; i

for (j=0; j

read(fd, buff, 1);

buff[1] = buff[0]>>4;

buff[2] = buff[0] & 0x0f;

*wr_buffer++ = pallete[buff[1]].red;

*wr_buffer++ = pallete[buff[1]].green;

*wr_buffer++ = pallete[buff[1]].blue;

*wr_buffer++ = pallete[buff[2]].red;

*wr_buffer++ = pallete[buff[2]].green;

*wr_buffer++ = pallete[buff[2]].blue;

}

if (x%2) {

read(fd, buff, 1);

buff[1] = buff[0]>>4;

*wr_buffer++ = pallete[buff[1]].red;

*wr_buffer++ = pallete[buff[1]].green;

*wr_buffer++ = pallete[buff[1]].blue;

}

if (skip) {

read(fd, buff, skip);

}

wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ }

break;

case 8: /* 8bit palletized */

skip = fill4B(x);

fetch_pallete(fd, pallete, 256);

lseek(fd, raster, SEEK_SET);

for (i=0; i

for (j=0; j

read(fd, buff, 1);

*wr_buffer++ = pallete[buff[0]].red;

*wr_buffer++ = pallete[buff[0]].green;

*wr_buffer++ = pallete[buff[0]].blue;

}

if (skip) {

read(fd, buff, skip);

}

wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ }

break;

case 16: /* 16bit RGB */

return(FH_ERROR_FORMAT);

break;

case 24: /* 24bit RGB */

skip = fill4B(x*3);

lseek(fd, raster, SEEK_SET);

for (i=0; i

for (j=0; j

read(fd, buff, 3);

*wr_buffer++ = buff[2];

*wr_buffer++ = buff[1];

*wr_buffer++ = buff[0];

}

if (skip) {

read(fd, buff, skip);

}

wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */

}

break;

default:

return(FH_ERROR_FORMAT);

}

close(fd);

return(FH_ERROR_OK);

#endif

}

intfh_bmp_getsize(char *name,int *x,int *y)

{

intfd;

unsigned char size[4];

fd = open(name, O_RDONLY);

if (fd == -1) {

return(FH_ERROR_FILE);//宏定义FH_ERROR_FILE 1; 见fbv.h

}

if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) {//BMP_SIZE_OFFSET :28

return(FH_ERROR_FORMAT);//FH_ERROR_FORMAT:2

}

read(fd, size, 4);

*x = size[0] + (size[1]<<8) + (size[2]<<16) + (size[3]<<24);

// *x-=1;

read(fd, size, 4);

*y = size[0] + (size[1]<<8) + (size[2]<<16) + (size[3]<<24);

close(fd);

return(FH_ERROR_OK);

}

#endif

//////////////////////////////////////////////////bmp.c///////////////////////////////////////////// //////////////////////////////////

//////////////////////////////////////////////////main.c///////////////////////////////////////////// //////////////////////////////////

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "config.h"

#include "fbv.h"

#include

#include

#if 1

#define UI_w 240

#define UI_h 320

/////////

unsigned char *fbdis = 0;

///////////

staticintopt_clear = 1,

opt_alpha = 0,

opt_hide_cursor = 1,

opt_image_info = 1,

opt_stretch = 0,

opt_delay = 0,

opt_enlarge = 0,

opt_ignore_aspect = 0;

intcmp;

voiddisplay_rgb( unsigned char * dis_data,intW,int H)

{

staticintfbfd = 0;

staticintkh=0;

inttfd=0;

structfb_var_screeninfovinfo;

structfb_fix_screeninfofinfo;

int blank=0;

longintscreensize = 0;

unsigned char * buf;

int x = 0, y = 0,z=0;

// Open the file for reading and writing

fbfd = open("/dev/fb0", O_RDWR);//打开显示设备

if (fbfd< 0) {

printf("Error: cannot open framebuffer device.\n");

exit(1);

}

// Get fixed screen information

if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {//

printf("Error reading fixed information.\n");

exit(2);

}

// Get variable screen information

if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {//获取屏的显示信息printf("Error reading variable information.\n");

exit(3);

}

printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );//vinfo.bits_per_pixel:每个像素

//所占比特,也就是biBitCount

// Figure out the size of the screen in bytes:计算出屏幕大小,单位bit screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

// Map the device to memory:映射设备到内存

/*

void *mmap(void *start, size_t length, intprot, int flags, intfd, off_toffsize);

mmap()建立内存映射:将某个文件内容映射到内存中,对该内存区域的存取即是对该文件内容的

读写。参数start指向欲对应的内存起始地址,通常设为NULL,代表让系统自动选定地址,对应成功后

该地址会返回。参数length代表将文件中多大的部分对应到内存。参数prot 代表映射区域的保护方式

有下列组合:PROT_EXEC 映射区域可被执行PROT_READ 映射区域可读PROT_WRITE 映射区域可写

PROT_NONE 映射区域不能存取参数flags会影响映射区域的各种特性。其中,MAP_SHARED:对映射区域的写入

数据会复制回文件中,而且允许其他映射该文件的进程共享参数fd为open()返回的文件描述符,

代表欲映射到内存的文件。参数offset为文件映射的偏移量,通常设置为0,代表从文件最前方开始对应

返回值:成功:返回映射区的内存起始地址,否则返回MAP_FATLED(-1),错误原因在errno中

*/

fbdis = (unsigned char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);

if ((int)fbdis == -1) {

printf("Error: failed to map framebuffer device to memory.\n");

exit(4);

}

intyy=0;

if(dis_data){

buf=fbdis;//往显示内存写入RBG

for ( y = 0; y < H/2; y++ )

for ( x = 0; x < W/2; x++ ) {

// buf[ y*Lcd_w*2+x*2] =(dis_data[y*W*3+x*3+2]>>3)|((dis_data[y*W*3+x*3+1]<<3)&0xe0);

// buf[ y*Lcd_w*2+x*2+1] = ((dis_data[y*W*3+x*3+1]>>5)&0x07)|(dis_data[y*W*3+x*3]&0xf8);

//dis_data[y*W*3+x*3]=0;

//dis_data[y*W*3+x*3+1]=x;

//dis_data[y*W*3+x*3+2]=0;

buf [ y*UI_w*2+x*2] =(((dis_data[y*W*3+x*3+2]>>3)&0x1f)|((dis_data[y*W*3+x*3+1]<<1)&0xe0));

buf [ y*UI_w*2+x*2+1] = (((dis_data[y*W*3+x*3+1]>>6)&0x07)|((dis_data[y*W*3+x*3]>>2)&0x78));

// buf [ y*UI_w*2+x*2+1] = ((dis_data[y*W*3+x*3]>>1)&0x78);

}

}

munmap(fbdis, screensize);//关闭设备

close(fbfd);

printf("end of display rgb\n");

}

intdisp_image(char *filename)//显示图片

{

int (*load)(char *, unsigned char *, unsigned char **, int, int);//申明加载

staticint k=1;

unsigned char * image = NULL;

unsigned char * alpha = NULL;

intx_size, y_size, screen_width, screen_height;

intx_pan, y_pan, x_offs, y_offs, refresh = 1, c, ret = 1;

int delay = opt_delay, retransform = 1;

inttransform_stretch = opt_stretch, transform_enlarge = opt_enlarge, transform_cal = (opt_stretch == 2),

transform_iaspect = opt_ignore_aspect, transform_rotation = 0;

#ifdef FBV_SUPPORT_GIF

if(fh_gif_id(filename))

if(fh_gif_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)

{

load = fh_gif_load;

goto identified1;

}

#endif

#ifdef FBV_SUPPORT_PNG

if(fh_png_id(filename))

if(fh_png_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)

{

load = fh_png_load;

goto identified1;

}

#endif

#ifdef FBV_SUPPORT_JPEG

if(fh_jpeg_id(filename))

if(fh_jpeg_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)

{

load = fh_jpeg_load;

goto identified1;

}

#endif

#ifdef FBV_SUPPORT_BMP

if(fh_bmp_id(filename))//判断是否为bmp格式,见bmp.c

if(fh_bmp_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)//读取图片信息

{

load = fh_bmp_load;

goto identified1;

}

#endif

printf("%s: Unable to access file or file format unknown.\n", filename);

return(1);

identified1:

if(!(image = (unsigned char*) malloc(x_size * y_size * 3)))

{

fprintf(stderr, "%s: Out of memory.\n", filename);

gotoerror_mem;

}

if(load(filename, image, &alpha, x_size, y_size) != FH_ERROR_OK)

{

fprintf(stderr, "%s: Image data is corrupt?\n", filename);

// gotoerror_mem;

}

if(!opt_alpha)

{

free(alpha);

alpha = NULL;

}

ret=0;

printf("dx=%d,dy=%d\n",x_size,y_size);

display_rgb(image,x_size,y_size);

done:

if(opt_clear)

{

// printf("\033[H\033[J");

fflush(stdout);

}

error_mem:

free(image);

free(alpha);

return(ret);

}

int main()

{

//////////////////////

/////

disp_image("1.bmp");

printf("begin main 00\n");

}

#endif

//////////////////////////////////////////////////main.c///////////////////////////////////////////// //////////////////////////////////

//////////////////////////////////////////////////config.h//////////////////////////////////////////// /////////////////////////////

#define IDSTRING "fbv 1.0b, s-tech"

#define DEFAULT_FRAMEBUFFER "/dev/fb0"

//#define FBV_SUPPORT_JPEG

//#define FBV_SUPPORT_PNG

#define FBV_SUPPORT_BMP

////////////////////////////////////////////////config.h////////////////////////////////////////////// /////////////////////////////

//////////////////////////////////////////////////fbv.h/////////////////////////////////////////////// ////////////////////////////////

/*

fbv -- simple image viewer for the linuxframebuffer

Copyright (C) 2000, 2001, 2003 MateuszGolicz

This program is free software; you can redistribute it and/or modify

it under the terms of the GNU General Public License as published by

the Free Software Foundation; either version 2 of the License, or

(at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#define FH_ERROR_OK 0

#define FH_ERROR_FILE 1 /* read/access error */

#define FH_ERROR_FORMAT 2 /* file format error */

intdis_w,dis_h;

intone_pic;

voidfb_display(unsigned char *rgbbuff, unsigned char * alpha, intx_size, inty_size, intx_pan, inty_pan, intx_offs, inty_offs);

voidgetCurrentRes(int *x, int *y);

intfh_bmp_id(char *name);

intfh_bmp_load(char *name,unsigned char *buffer, unsigned char **alpha, intx,int y);

intfh_bmp_getsize(char *name,int *x,int *y);

intfh_jpeg_id(char *name);

intfh_jpeg_load(char *name,unsigned char *buffer, unsigned char **alpha, intx,int y);

intfh_jpeg_getsize(char *name,int *x,int *y);

intfh_png_id(char *name);

intfh_png_load(char *name,unsigned char *buffer, unsigned char **alpha, intx,int y);

intfh_png_getsize(char *name,int *x,int *y);

intfh_gif_id(char *name);

intfh_gif_load(char *name,unsigned char *buffer, unsigned char **alpha, intx,int y);

intfh_gif_getsize(char *name,int *x,int *y);

struct image

{

int width, height;

unsigned char *rgb;

unsigned char *alpha;

intdo_free;

};

#ifndef min

#define min(a,b) ((a) < (b) ? (a) : (b))

#endif

#ifndef max

#define max(a,b) ((a) > (b) ? (a) : (b))

#endif

unsigned char * simple_resize(unsigned char * orgin,intox,intoy,intdx,intdy);

unsigned char * alpha_resize(unsigned char * alpha,intox,intoy,intdx,intdy);

unsigned char * color_average_resize(unsigned char * orgin,intox,intoy,intdx,intdy);

unsigned char * rotate(unsigned char *i, int ox, intoy, int rot);

unsigned char * alpha_rotate(unsigned char *i, int ox, intoy, int rot);

voidcenter_resize_qcif(char *disy_buf,char *inpic_buf,intin_w,intin_h);

//////////////////////////////////////////////////fbv.h///////////////////////////////////////////////

////////////////////////////////

//////////////////////////////////////////////////makefile/////////////////////////////////////////// ////////////////////////////////////

#

# Makefile

#

includeMake.conf

CC = arm-linux-gcc

CFLAGS = -O2 -Wall -D_GNU_SOURCE -I/usr/local/include/ # -L/usr/local/lib

SOURCES =main.cbmp.c #in_device.c

OBJECTS = ${SOURCES:.c=.o}

OUT = fbs

#LIBS = -lungif -L/usr/X11R6/lib -ljpeg -lpng

all: $(OUT)

@echo Build DONE.

$(OUT): $(OBJECTS)

$(CC) $(LDFLAGS) $(CFLAGS) -o $(OUT) $(OBJECTS) $(LIBS) $ -lpthread

clean:

rm -f $(OBJECTS) *~ $$$$~* *.bak core config.log $(OUT)

distclean: clean

@echo -e "error:\n\t@echo Please run ./configure first..." >Make.conf

rm -f $(OUT) config.h

install: $(OUT)

cp $(OUT) $(DESTDIR)$(bindir)

gzip -9c $(OUT).1 > $(DESTDIR)$(mandir)/man1/$(OUT).1.gz

uninstall: $(DESTDIR)$(bindir)/$(OUT)

rm -f $(DESTDIR)$(bindir)/$(OUT)

rm -f $(DESTDIR)$(mandir)/man1/$(OUT).1.gz

//////////////////////////////////////////////////makefile/////////////////////////////////////////// ////////////////////////////////////

如何安装Linux内核源代码

如何获取Linux内核源代码 下载Linux内核当然要去官方网站了,网站提供了两种文件下载,一种是完整的Linux 内核,另一种是内核增量补丁,它们都是tar归档压缩包。除非你有特别的原因需要使用旧版本的Linux内核,否则你应该总是升级到最新版本。 使用Git 由Linus领头的内核开发队伍从几年前就开始使用Git版本控制系统管理Linux内核了(参考阅读:什么是Git?),而Git项目本身也是由Linus创建的,它和传统的CVS不一样,Git是分布式的,因此它的用法和工作流程很多开发人员可能会感到很陌生,但我强烈建议使用Git下载和管理Linux内核源代码。 你可以使用下面的Git命令获取Linus内核代码树的最新“推送”版本: $ git clone git://https://www.360docs.net/doc/061935068.html,/pub/scm/linux/kernel/git/torvalds/linux-2.6.git 然后使用下面的命令将你的代码树与Linus的代码树最新状态同步: $ git pull 安装内核源代码 内核包有GNU zip(gzip)和bzip2格式。Bzip2是默认和首选格式,因为它的压缩比通常比gzip更好,bzip2格式的Linux内核包一般采用linux-x.y.z.tar.bz2形式的文件名,这里的x.y.z是内核源代码的具体版本号,下载到源代码包后,解压和抽取就很简单了,如果你下载的是bzip2包,运行: $ tar xvjf linux-x.y.z.tar.bz2 如果你下载的是gzip包,则运行: $ tar xvzf linux-x.y.z.tar.gz 无论执行上面哪一个命令,最后都会将源代码解压和抽取到linux-x.y.z目录下,如果你使用Git下载和管理内核源代码,你不需要下载tar包,只需要运行git clone命令,它就会自动下载和解压。 内核源代码通常都会安装到/usr/src/linux下,但在开发的时候最好不要使用这个源代码树,因为针对你的C库编译的内核版本通常也链接到这里的。 应用补丁

Linux操作系统源代码详细分析

linux源代码分析:Linux操作系统源代码详细分析 疯狂代码 https://www.360docs.net/doc/061935068.html,/ ?:http:/https://www.360docs.net/doc/061935068.html,/Linux/Article28378.html 内容介绍: Linux 拥有现代操作系统所有功能如真正抢先式多任务处理、支持多用户内存保护虚拟内存支持SMP、UP符合POSIX标准联网、图形用户接口和桌面环境具有快速性、稳定性等特点本书通过分析Linux内核源代码充分揭示了Linux作为操作系统内核是如何完成保证系统正常运行、协调多个并发进程、管理内存等工作现实中能让人自由获取系统源代码并不多通过本书学习将大大有助于读者编写自己新 第部分 Linux 内核源代码 arch/i386/kernel/entry.S 2 arch/i386/kernel/init_task.c 8 arch/i386/kernel/irq.c 8 arch/i386/kernel/irq.h 19 arch/i386/kernel/process.c 22 arch/i386/kernel/signal.c 30 arch/i386/kernel/smp.c 38 arch/i386/kernel/time.c 58 arch/i386/kernel/traps.c 65 arch/i386/lib/delay.c 73 arch/i386/mm/fault.c 74 arch/i386/mm/init.c 76 fs/binfmt-elf.c 82 fs/binfmt_java.c 96 fs/exec.c 98 /asm-generic/smplock.h 107 /asm-i386/atomic.h 108 /asm- i386/current.h 109 /asm-i386/dma.h 109 /asm-i386/elf.h 113 /asm-i386/hardirq.h 114 /asm- i386/page.h 114 /asm-i386/pgtable.h 115 /asm-i386/ptrace.h 122 /asm-i386/semaphore.h 123 /asm-i386/shmparam.h 124 /asm-i386/sigcontext.h 125 /asm-i386/siginfo.h 125 /asm-i386/signal.h 127 /asm-i386/smp.h 130 /asm-i386/softirq.h 132 /asm-i386/spinlock.h 133 /asm-i386/system.h 137 /asm-i386/uaccess.h 139 //binfmts.h 146 //capability.h 147 /linux/elf.h 150 /linux/elfcore.h 156 /linux/errupt.h 157 /linux/kernel.h 158 /linux/kernel_stat.h 159 /linux/limits.h 160 /linux/mm.h 160 /linux/module.h 164 /linux/msg.h 168 /linux/personality.h 169 /linux/reboot.h 169 /linux/resource.h 170 /linux/sched.h 171 /linux/sem.h 179 /linux/shm.h 180 /linux/signal.h 181 /linux/slab.h 184 /linux/smp.h 184 /linux/smp_lock.h 185 /linux/swap.h 185 /linux/swapctl.h 187 /linux/sysctl.h 188 /linux/tasks.h 194 /linux/time.h 194 /linux/timer.h 195 /linux/times.h 196 /linux/tqueue.h 196 /linux/wait.h 198 init/.c 198 init/version.c 212 ipc/msg.c 213 ipc/sem.c 218 ipc/shm.c 227 ipc/util.c 236 kernel/capability.c 237 kernel/dma.c 240 kernel/exec_do.c 241 kernel/exit.c 242 kernel/fork.c 248 kernel/info.c 255 kernel/itimer.c 255 kernel/kmod.c 257 kernel/module.c 259 kernel/panic.c 270 kernel/prk.c 271 kernel/sched.c 275 kernel/signal.c 295 kernel/softirq.c 307 kernel/sys.c 307 kernel/sysctl.c 318 kernel/time.c 330 mm/memory.c 335 mm/mlock.c 345 mm/mmap.c 348 mm/mprotect.c 358 mm/mremap.c 361 mm/page_alloc.c 363 mm/page_io.c 368 mm/slab.c 372 mm/swap.c 394 mm/swap_state.c 395 mm/swapfile.c 398 mm/vmalloc.c 406 mm/vmscan.c 409

linux 基本操作命令行

linux的命令操作 1、日常操作命令 **查看当前所在的工作目录 pwd **查看当前系统的时间 date **查看有谁在线(哪些人登陆到了服务器) who 查看当前在线 last 查看最近的登陆历史记录 2、文件系统操作 ** ls / 查看根目录下的子节点(文件夹和文件)信息 ls -al -a是显示隐藏文件 -l是以更详细的列表形式显示 **切换目录 cd /home **创建文件夹 mkdir aaa 这是相对路径的写法 mkdir -p aaa/bbb/ccc mkdir /data 这是绝对路径的写法 **删除文件夹 rmdir 可以删除空目录 rm -r aaa 可以把aaa整个文件夹及其中的所有子节点全部删除 rm -rf aaa 强制删除aaa **修改文件夹名称 mv aaa angelababy **创建文件 touch somefile.1 创建一个空文件 echo "i miss you,my baby" > somefile.2 利用重定向“>”的功能,将一条指令的输出结果写入到一个文件中,会覆盖原文件内容 echo "huangxiaoming ,gun dan" >> somefile.2 将一条指令的输出结果追加到一个文件中,不会覆盖原文件内容 用vi文本编辑器来编辑生成文件 ******最基本用法 vi somefile.4

1、首先会进入“一般模式”,此模式只接受各种快捷键,不能编辑文件内容 2、按i键,就会从一般模式进入编辑模式,此模式下,敲入的都是文件内容 3、编辑完成之后,按Esc键退出编辑模式,回到一般模式; 4、再按:,进入“底行命令模式”,输入wq命令,回车即可 ******一些常用快捷键 一些有用的快捷键(在一般模式下使用): a 在光标后一位开始插入 A 在该行的最后插入 I 在该行的最前面插入 gg 直接跳到文件的首行 G 直接跳到文件的末行 dd 删除行,如果 5dd ,则一次性删除光标后的5行 yy 复制当前行, 复制多行,则 3yy,则复制当前行附近的3行 p 粘贴 v 进入字符选择模式,选择完成后,按y复制,按p粘贴 ctrl+v 进入块选择模式,选择完成后,按y复制,按p粘贴 shift+v 进入行选择模式,选择完成后,按y复制,按p粘贴 查找并替换(在底行命令模式中输入) %s/sad/88888888888888 效果:查找文件中所有sad,替换为88888888888888 /you 效果:查找文件中出现的you,并定位到第一个找到的地方,按n可以定位到下一个匹配位置(按N定位到上一个) 3、文件权限的操作 ****linux文件权限的描述格式解读 drwxr-xr-x (也可以用二进制表示 111 101 101 --> 755) d:标识节点类型(d:文件夹 -:文件 l:链接) r:可读 w:可写 x:可执行 第一组rwx:表示这个文件的拥有者对它的权限:可读可写可执行 第二组r-x:表示这个文件的所属组对它的权限:可读,不可写,可执行 第三组r-x:表示这个文件的其他用户(相对于上面两类用户)对它的权限:可读,不可写,可执行 ****修改文件权限 chmod g-rw haha.dat 表示将haha.dat对所属组的rw权限取消 chmod o-rw haha.dat 表示将haha.dat对其他人的rw权限取消 chmod u+x haha.dat 表示将haha.dat对所属用户的权限增加x 也可以用数字的方式来修改权限 chmod 664 haha.dat 就会修改成 rw-rw-r--

关于Linux 内核中五个主要子系统的介绍

关于Linux 内核中五个主要子系统的介绍 发布时间:2008.01.02 06:23来源:赛迪网作者:sixth 1.进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。 2.内存管理(MM)允许多个进程安全的共享主内存区域。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码,数据,堆栈的总量可以超过实际内存的大小,操作系统只是把当前使用的程序块保留在内存中,其余的程序块则保留在磁盘中。必要时,操作系统负责在磁盘和内存间交换程序块。内存管理从逻辑上分为硬件无关部分和硬件有关部分。硬件无关部分提供了进程的映射和逻辑内存的对换;硬件相关的部分为内存管理硬件提供了虚拟接口。 3.虚拟文件系统(VirtualFileSystem,VFS)隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2,fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。 4.网络接口(NET)提供了对各种网络标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。 5.进程间通讯(IPC) 支持进程间各种通信机制。处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程被恢复执行。例如,当一个进程通过网络发送一条消息时,网络接口需要挂起发送进程,直到硬件成功地完成消息的发送,当消息被成功的发送出去以后,网络接口给进程返回一个代码,表示操作的成功或失败。其他子系统以相似的理由依赖于进程调度。

linux内核IMQ源码实现分析

本文档的Copyleft归wwwlkk所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性,严禁用于任何商业用途。 E-mail: wwwlkk@https://www.360docs.net/doc/061935068.html, 来源: https://www.360docs.net/doc/061935068.html,/?business&aid=6&un=wwwlkk#7 linux2.6.35内核IMQ源码实现分析 (1)数据包截留并重新注入协议栈技术 (1) (2)及时处理数据包技术 (2) (3)IMQ设备数据包重新注入协议栈流程 (4) (4)IMQ截留数据包流程 (4) (5)IMQ在软中断中及时将数据包重新注入协议栈 (7) (6)结束语 (9) 前言:IMQ用于入口流量整形和全局的流量控制,IMQ的配置是很简单的,但很少人分析过IMQ的内核实现,网络上也没有IMQ的源码分析文档,为了搞清楚IMQ的性能,稳定性,以及借鉴IMQ的技术,本文分析了IMQ的内核实现机制。 首先揭示IMQ的核心技术: 1.如何从协议栈中截留数据包,并能把数据包重新注入协议栈。 2.如何做到及时的将数据包重新注入协议栈。 实际上linux的标准内核已经解决了以上2个技术难点,第1个技术可以在NF_QUEUE机制中看到,第二个技术可以在发包软中断中看到。下面先介绍这2个技术。 (1)数据包截留并重新注入协议栈技术

(2)及时处理数据包技术 QoS有个技术难点:将数据包入队,然后发送队列中合适的数据包,那么如何做到队列中的数

激活状态的队列是否能保证队列中的数据包被及时的发送吗?接下来看一下,激活状态的队列的 证了数据包会被及时的发送。 这是linux内核发送软中断的机制,IMQ就是利用了这个机制,不同点在于:正常的发送队列是将数据包发送给网卡驱动,而IMQ队列是将数据包发送给okfn函数。

Linux 用户必知:一分钟掌握14个常用Linux命令行快捷键

Linux 用户必知:一分钟掌握14个常用Linux命令行快捷键 2018.10.29 前几天有个朋友给我发消息:“问你个问题,Linux 命令行有没有快捷键一下从行末会到行头?经常敲了很多命令发现忘加sudo 了,然后把命令删了重新敲一遍”。 正好借此机会给不知道的朋友总结一下: 首先说说历史记录个数的“HISTFILESIZE”和“HISTSIZE”的区别默认情况下HISTFILESIZE 和HISTSIZE的值都是500,表示可以记录500 条命令记录。 ·HISTFILESIZE 表示记录在文件中的命令条数 · HISTSIZE 表示记录在内存中的命令条数 当我们在 shell 命令行执行命令的时候,最近的HISTSIZE 条命令被保存在内存当中可以使用上下光标或者ctrl+p,ctrl+n 上下查找命令。 当退出shell 时HISTFILESIZE 条命令被保存到历史命令文件中,下次登录shell 时会从历史命令文件中读取命令道内存历史命令道中。 当网络中断等异常时,你会发现之前的历史命令,下次登录时用上下光标找不到上次的历史命令,所以要正常退出或者发送探测包保持shell 在线。 如果想增加历史命令保存的数量,可以在~/.bash_profile 中手动修改HISTFILESIZE 和HISTSIZE 这两个变量的值。 必须知道的Linux命令行 我想提一下一些快捷键可能依赖于你使用的Shell。Bash 是最受欢迎的shell,所以列出的快捷键集中在Bash。如果你愿意,你也可以称其为Bash 快捷键列表。 注意我在键盘快捷键中使用了大写字母,但这并不意味着你在使用快捷键时必须按下

Linux源代码下载

1. 课程设计题目:下载某个版本的linux源代码,生成一个定制的linux操作系统,完成后该系统可以用来作为启动系统使用。 2.如何做的问题? 内核版本要编译一个最新的内核,您需要首先下载它的源代码在您下载内核的源代码前,您要知道到您要找什么。首先要问您自己的问题是-- 您需要一份稳定的还是测试版的内核?稳定版内核通常版本号第二位用偶数数字 -- 例如, 2.0.38、2.2.15、2.2.1 8 和2.4.1 是被认为是“稳定”的内核(分别由于其包含 0、2、2 和4)。如果您想尝试测试版内核,您通常需要找那些版本号第二位是奇数的号码又最高的内核。例如,2.3.99 和 2.1.38都是测试版内核(分别由于其包含 3 和 1)。 内核版本历史 2.2 系列的内核被认为是较新而且稳定的内核。如果"较新"和"稳定"是您想要的,查找一个版本号的第三位是最高的2.2 内核(2.2.16 是目前最新的版本)。当 2.2 系列的内核仍在开发中,2.3 系列已经开始了。这个系列是作为将被集成到 2.4稳定版系列的新功能和高级功能的测试版。2.3 系列已经到了 2.3.99,其开发已经停止。开发人员已经开始着手2.4.0。如果您喜欢冒险使用最最新的技术,您可能想使用可以找到的最新的 2.4 系列内核。

2.4 版内核警告信息 Once a real 2.4 series kernel comes out(like 2.4.0), don't assume that the kernel is ready for use on a mission-critical system like a server. Even though 2.4 is supposed tobe a stable series, early 2.4 kernels ar e likely to be not quite up tosnuff. As is often the case i n the computer industry, the first version o f anythin g can have fairly sizable bugs. While this may not be a problem i f you're testing the kernel on your home workstation, it is a risk you may want to avoid when you machine provides val uable services to others. 下载内核 如果您只是想编译一个您已安装内核的新版本(例如,实现 SMP 支持),那不需要下载任何代码 -- 跳过此部分继续下一屏。 您可以在https://www.360docs.net/doc/061935068.html,/pub/linux/kernel上找到内核代码。当您进入到那后,您将发现内核的源代码按内核版本(v2.2、v 2.3等),被组织到多个不同的目录中。在每个目录中,您将发现文件被冠以"linux-x.y.z.tar.gz"和"linux-x.y.z.tar.bz2"。这些就是Linux 内核的源代码。您也将看到冠以 "patch-x.y.z.gz" 和"pa tch-x.y.z.bz2"的文件。这些是用来更新前面完整的内核源代码的补丁包。如果您希望编译一个新的内核版本,您将需要下载这些"linu x"文件其中之一。

读Linux内核源代码

Linux内核分析方法 Linux的最大的好处之一就是它的源码公开。同时,公开的核心源码也吸引着无数的电脑爱好者和程序员;他们把解读和分析Linux的核心源码作为自己的最大兴趣,把修改Linux源码和改造Linux系统作为自己对计算机技术追求的最大目标。 Linux内核源码是很具吸引力的,特别是当你弄懂了一个分析了好久都没搞懂的问题;或者是被你修改过了的内核,顺利通过编译,一切运行正常的时候。那种成就感真是油然而生!而且,对内核的分析,除了出自对技术的狂热追求之外,这种令人生畏的劳动所带来的回报也是非常令人着迷的,这也正是它拥有众多追随者的主要原因: ?首先,你可以从中学到很多的计算机的底层知识,如后面将讲到的系统的引导和硬件提供的中断机制等;其它,象虚拟存储的实现机制,多任务机制,系统保护机制等等,这些都是非都源码不能体会的。 ?同时,你还将从操作系统的整体结构中,体会整体设计在软件设计中的份量和作用,以及一些宏观设计的方法和技巧:Linux的内核为上层应用提供一个与具体硬件不相关的平台; 同时在内核内部,它又把代码分为与体系结构和硬件相关的部分,和可移植的部分;再例如,Linux虽然不是微内核的,但他把大部分的设备驱动处理成相对独立的内核模块,这样减小了内核运行的开销,增强了内核代码的模块独立性。 ?而且你还能从对内核源码的分析中,体会到它在解决某个具体细节问题时,方法的巧妙:如后面将分析到了的Linux通过Botoom_half机制来加快系统对中断的处理。 ?最重要的是:在源码的分析过程中,你将会被一点一点地、潜移默化地专业化。一个专业的程序员,总是把代码的清晰性,兼容性,可移植性放在很重要的位置。他们总是通过定义大量的宏,来增强代码的清晰度和可读性,而又不增加编译后的代码长度和代码的运行效率; 他们总是在编码的同时,就考虑到了以后的代码维护和升级。甚至,只要分析百分之一的代码后,你就会深刻地体会到,什么样的代码才是一个专业的程序员写的,什么样的代码是一个业余爱好者写的。而这一点是任何没有真正分析过标准代码的人都无法体会到的。 然而,由于内核代码的冗长,和内核体系结构的庞杂,所以分析内核也是一个很艰难,很需要毅力的事;在缺乏指导和交流的情况下,尤其如此。只有方法正确,才能事半功倍。正是基于这种考虑,作者希望通过此文能给大家一些借鉴和启迪。 由于本人所进行的分析都是基于2.2.5版本的内核;所以,如果没有特别说明,以下分析都是基于i386单处理器的2.2.5版本的Linux内核。所有源文件均是相对于目录/usr/src/linux的。 方法之一:从何入手 要分析Linux内核源码,首先必须找到各个模块的位置,也即要弄懂源码的文件组织形式。虽然对于有经验的高手而言,这个不是很难;但对于很多初级的Linux爱好者,和那些对源码分析很

Linux内核源代码阅读与工具介绍

Linux的内核源代码可以从很多途径得到。一般来讲,在安装的linux系统下,/usr/src/linux 目录下的东西就是内核源代码。另外还可以从互连网上下载,解压缩后文件一般也都位于linux目录下。内核源代码有很多版本,目前最新的版本是2.2.14。 许多人对于阅读Linux内核有一种恐惧感,其实大可不必。当然,象Linux内核这样大而复杂的系统代码,阅读起来确实有很多困难,但是也不象想象的那么高不可攀。只要有恒心,困难都是可以克服的。任何事情做起来都需要有方法和工具。正确的方法可以指导工作,良好的工具可以事半功倍。对于Linux内核源代码的阅读也同样如此。下面我就把自己阅读内核源代码的一点经验介绍一下,最后介绍Window平台下的一种阅读工具。 对于源代码的阅读,要想比较顺利,事先最好对源代码的知识背景有一定的了解。对于linux内核源代码来讲,基本要求是:⑴操作系统的基本知识;⑵对C语言比较熟悉,最好要有汇编语言的知识和GNU C对标准C的扩展的知识的了解。另外在阅读之前,还应该知道Linux内核源代码的整体分布情况。我们知道现代的操作系统一般由进程管理、内存管理、文件系统、驱动程序、网络等组成。看一下Linux内核源代码就可看出,各个目录大致对应了这些方面。Linux内核源代码的组成如下(假设相对于linux目录): arch这个子目录包含了此核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是i386。 include这个目录包括了核心的大多数include文件。另外对于每种支持的体系结构分别有一个子目录。 init此目录包含核心启动代码。 mm此目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下,如对应于X86的就是arch/i386/mm/fault.c。 drivers系统中所有的设备驱动都位于此目录中。它又进一步划分成几类设备驱动,每一种也有对应的子目录,如声卡的驱动对应于drivers/sound。 ipc此目录包含了核心的进程间通讯代码。 modules此目录包含已建好可动态加载的模块。 fs Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext2文件系统对应的就是ext2子目录。 kernel主要核心代码。同时与处理器结构相关代码都放在arch/*/kernel目录下。 net核心的网络部分代码。里面的每个子目录对应于网络的一个方面。 lib此目录包含了核心的库代码。与处理器结构相关库代码被放在arch/*/lib/目录下。

Linux内核编码风格(编程代码风格推荐)

这是翻译版本,英文原版是linux源码Documentation文件夹下的CodingStyle 一个良好风格的程序看起来直观、美观,便于阅读,还能有助于对程序的理解,特别在代码量比较大情况下更显现编码素质的重要性。相反没有良好的风格的代码读起来难看、晦涩,甚至有时候一个括号没对齐就能造成对程序的曲解或者不理解。我曾经就遇见过这样的情况,花费了很多不必要的时间在程序的上下文对照上,还debug了半天没理解的程序。后来直接用indent -kr -i8给他转换格式来看了。特此转过来一个关于代码风格的帖子分享一下~ Linux内核编码风格 这是一份简短的,描述linux内核首选编码风格的文档。编码风格是很个人化的东西,而且我也不愿意把我的观点强加给任何人,不过这里所讲述的是我必须要维护的代码所遵守的风格,并且我也希望绝大多数其他代码也能遵守这个风格。所以请至少考虑一下本文所述的观点。 首先,我建议你打印一份GNU的编码规范,然后不要读它。烧掉它,这是一个很高调的具有象征意义的姿态。 Anyway, here goes: 第一章:缩进 制表符是8个字符,所以缩进也是8个字符。有些异端运动试图将缩进变为4(乃至2)个字符深,这跟尝试着将圆周率PI的值定义为3没什么两样。 理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的屏幕连续看了20小时之后,你将会发现大一点的缩进将会使你更容易分辨缩进。 现在,有些人会抱怨8个字符的缩进会使代码向右边移动的太远,在80个字符的终端屏幕上就很难读这样的代码。这个问题的答案是,如果你需要3级以上的缩进,不管缩进深度如何你的代码已经有问题了,应该修正你的程序。 简而言之,8个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太深的时候可以向你提出告警。请留意这个警告。 在switch语句中消除多级缩进的首选的方式是让“switch”和从属于它的“case”标签对 齐于同一列,而不要“两次缩进”“case”标签。比如: switch (suffix) { case 'G': case 'g': mem <<= 30;

linux源代码分析实验报告格式

linux源代码分析实验报告格式

Linux的fork、exec、wait代码的分析 指导老师:景建笃 组员:王步月 张少恒 完成日期:2005-12-16

一、 设计目的 1.通过对Linux 的fork 、exec 、wait 代码的分析,了解一个操作系统进程的创建、 执行、等待、退出的过程,锻炼学生分析大型软件代码的能力; 2.通过与同组同学的合作,锻炼学生的合作能力。 二、准备知识 由于我们选的是题目二,所以为了明确分工,我们必须明白进程的定义。经过 查阅资料,我们得知进程必须具备以下四个要素: 1、有一段程序供其执行。这段程序不一定是进程专有,可以与其他进程共用。 2、有起码的“私有财产”,这就是进程专用的系统堆栈空间 3、有“户口”,这就是在内核中有一个task_struct 结构,操作系统称为“进程控制 块”。有了这个结构,进程才能成为内核调度的一个基本单位。同时,这个结构又 是进程的“财产登记卡”,记录着进程所占用的各项资源。 4、有独立的存储空间,意味着拥有专有的用户空间:进一步,还意味着除前述的 系统空间堆栈外,还有其专用的用户空间堆栈。系统为每个进程分配了一个 task_struct 结构,实际分配了两个连续的物理页面(共8192字节),其图如下: Struct task_struct (大约1K) 系统空间堆栈 (大约7KB )两个 连续 的物 理页 面 对这些基本的知识有了初步了解之后,我们按老师的建议,商量分工。如下: 四、 小组成员以及任务分配 1、王步月:分析进程的创建函数fork.c ,其中包含了get_pid 和do_fork get_pid, 写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作 比例35%。 2、张少恒:分析进程的执行函数exec.c,其中包含了do_execve 。写出代码分析结 果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例35% 。 3、余波:分析进程的退出函数exit.c,其中包含了do_exit 、sys_wait4。写出代码 分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例30% 。 五、各模块分析: 1、fork.c 一)、概述 进程大多数是由FORK 系统调用创建的.fork 能满足非常高效的生灭机制.除了 0进程等少数一,两个进程外,几乎所有的进程都是被另一个进程执行fork 系统调 用创建的.调用fork 的进程是父进程,由fork 创建的程是子进程.每个进程都有一

Linux命令大全(设备管理)

设备管理-setleds 名称:setleds 使用权限:一般使用者 使用方式: setleds [-v] [-L] [-D] [-F] [{+|-}num] [{+|-}caps] [{+|-}scroll]说明: 用来设定键盘上方三个LED 的状态。在Linux 中,每一个虚拟主控台都有独立的设定。 参数: -F 预设的选项,设定虚拟主控台的状态。 -D 除了改变虚拟主控台的状态外,还改变预设的状态。 -L 不改变虚拟主控台的状态,但直接改变LED 显示的状态。这会使得LDE 显示和目前虚拟主控台的状态不符合。我们可以在稍后用-L 且不含其它选项的setleds 命令回复正常状态。 -num +num 将数字键打开或关闭。 -caps +caps 把大小写键打开或关闭。 -scroll +scroll 把选项键打开或关闭。 范例: 将数字键打开,其馀二个灯关闭。 # setleds +num -caps -scroll 设备管理-loadkeys 名称: loadkeys 使用权限: 所有使用者

使用方式: loadkeys [ -d --default ] [ -h --help ] [ -q --quiet ] [ -v --verbose [ -v --verbose ]...] [ -m --mktable ] [ -c --clearcompose ] [ -s --clearstrings ] [ filename... ] 使用说明: 这个命令可以根据一个键盘定义表改变linux 键盘驱动程序转译键盘输入过程。详细的说明请参考dumpkeys。 选项: -v --verbose 印出详细的资料,你可以重复以增加详细度。 -q --quiet 不要显示任何讯息。 -c --clearcompose 清除所有composite 定义。 -s --clearstrings 将定串定义表清除。 相关命令: dumpkeys 设备管理-rdev 名称:rdev 使用权限:所有使用者 使用方式:使用这个指令的基本方式是:rdev [-rsvh ] [-o offset ] [ image [value [ offset ] ] ] 但是随著使用者想要设定的参数的不同,底下的方式也是一样: rdev [ -o offset ] [ image [ root_device [ offset ] ] ] swapdev [ -o offset ] [ image [ swap_device [ offset ] ] ] ramsize [ -o offset ] [ image [ size [ offset ] ] ] videomode [ -o offset ] [ image [ mode [ offset ] ] ] rootflags [ -o offset ] [ image [ flags [ offset ] ] ]

Linux源代码分析_存储管理

文章编号:1004-485X (2003)03-0030-04 收稿日期:2003-05-10 作者简介:王艳春,女(1964 ),副教授,主要从事操作系统、中文信息处理等方面的研究工作。 Linux 源代码分析 存储管理 王艳春 陈 毓 葛明霞 (长春理工大学计算机科学技术学院,吉林长春130022) 摘 要:本文剖析了Linux 操作系统的存储管理机制。给出了Linux 存储管理的特点、虚存的实现方法,以及主要数据结构之间的关系。 关键词:Linux 操作系统;存储管理;虚拟存储中图分类号:T P316 81 文献标识码:A Linux 操作系统是一种能运行于多种平台、源代码公开、免费、功能强大、与Unix 兼容的操作系统。自其诞生以来,发展非常迅速,在我国也受到政府、企业、科研单位、大专院校的重视。我们自2000年开始对Linux 源代码(版本号是Linux 2 2 16)进行分析,首先剖析了进程管理和存储管理部分,本文是有关存储管理的一部分。主要介绍了Linux 虚存管理所用到的数据结构及其相互间的关系,据此可以更好地理解其存储管理机制,也可以在此基础上对其进行改进或在此后的研究中提供借鉴作用。作为一种功能强大的操作系统,Linux 实现了以虚拟内存为主的内存管理机制。即能够克服物理内存的局限,使用户进程在透明方式下,拥有比实际物理内存大得多的内存。本文主要阐述了Linux 虚存管理的基本特点和主要实现技术,并分析了Linux 虚存管理的主要数据结构及其相互关系。 1 Lin ux 虚存管理概述 Linux 的内存管理采用虚拟页式管理,使用多级页表,动态地址变换。进程在运行过程中可以动态浮动和扩展,为用户提供了透明的、灵活有效的内存使用方式。 1)32 bit 虚拟地址 在Linux 中,进程的4GB 虚存需通过32 bit 地址进行寻址。Linux 中虚拟地址与线性地址为同一概念,虚拟地址被分成3个子位段,而大小为4k,如图1所示。 2)Linux 的多级页表结构 图1 32位虚拟地址 标准的Linux 的虚存页表为三级页表,依次为页目录(Pag e Directory PGD)、中间页目录(Pag e Middle Directory PMD )、页表(Page Table PT E )。在i386机器上Linux 的页表结构实际为两级,PGD 和PMD 页表是合二为一的。所有有关PMD 的操作关际上是对PGD 的操作。所以源代码中形如*_pgd _*()和*_pmd_*()函数实现的功能也是一样的。 页目录(PGD)是一个大小为4K 的表,每一个进程只有一个页目录,以4字节为一个表项,分成1024个表项(或称入口点),表项的索引即为32位虚拟地址的页目录,该表项的值为所指页表的起始地址。页表(PTE)的每一个入口点的值为此表项所指的一页框(page frame),页表项的索引即为32位虚拟地址中的页号。页框(page reame)并不是物理页,它指的是虚存的一个地址空间。 3) 页表项的格式 图2 Linux 中页目录项和页表项格式 4)动态地址映射 Linux 虚存采用动态地址映射方式,即进程的地址空间和存储空间的对应关系是在程序的执行过 第26卷第3期长春理工大学学报 Vol 26N o 32003年9月 Journal of Changchun University of Science and T echnology Sep.2003

Linux内核版本号及源代码目录树结构

Linux 内核版本号及源代码目录树结构 一、linux内核版本号的命名机制 Linux内核版本有两种:稳定版和开发版。稳定的内核具有工业级的强度,可以广泛地应用和部署。新的稳定内核相对于较旧的只是修正一些bug或加入一些新的驱动程序。而开发版内核由于要试验各种解决方案,所以变化很快。这两种版本是相互关联,相互循环的。 Linux内核的命名机制: num.num.num 其中第一个数字是主版本号,第二个数字是次版本号,第三个数字是修订版本号。如果次版本号是偶数,那么该内核就是稳定版的;若是奇数,则是开发版的。头两个数字合在一齐可以描述内核系列。如稳定版的2.6.0,它是2.6版内核系列。最新的内核源代码可以在https://www.360docs.net/doc/061935068.html,以tar包或者增量补丁的形式下载.。 Linux还有各种发行版本,除了最熟悉的Redhat,Debian,Bluepoint,红旗,还有 Slackware,Mandarke,Turbo。 二、linux源代码目录树结构 Linux用来支持各种体系结构的源代码包含大约4500个C语言程序,存放在270个左右的子目录下,总共大约包含200万行代码,大概占用58MB磁盘空间。 在阅读源码之前,还应知道Linux内核源码的整体分布情况。现代的操作系统一般由进程管理、内存管理、文件系统、驱动程序和网络等组成。Linux内核源码的各个目录大致与此相对应,其组成如下: arch目录包括了所有和体系结构相关的核心代码。它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录。PC机一般都基于此目录。 include目录包括编译核心所需要的大部分头文件,例如与平台无关的头文件在include/linux子目录下。

Linux内核源码分析方法

Linux内核源码分析方法 一、内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次。如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径。我们都知道,想成为优秀的程序员,需要大量的实践和代码的编写。编程固然重要,但是往往只编程的人很容易把自己局限在自己的知识领域内。如果要扩展自己知识的广度,我们需要多接触其他人编写的代码,尤其是水平比我们更高的人编写的代码。通过这种途径,我们可以跳出自己知识圈的束缚,进入他人的知识圈,了解更多甚至我们一般短期内无法了解到的信息。Linux内核由无数开源社区的“大神们”精心维护,这些人都可以称得上一顶一的代码高手。透过阅读Linux 内核代码的方式,我们学习到的不光是内核相关的知识,在我看来更具价值的是学习和体会它们的编程技巧以及对计算机的理解。 我也是通过一个项目接触了Linux内核源码的分析,从源码的分析工作中,我受益颇多。除了获取相关的内核知识外,也改变了我对内核代码的过往认知: 1.内核源码的分析并非“高不可攀”。内核源码分析的难度不在于源码本身,而在于如何使用更合适的分析代码的方式和手段。内核的庞大致使我们不能按照分析一般的demo程序那样从主函数开始按部就班的分析,我们需要一种从中间介入的手段对内核源码“各个击破”。这种“按需索取”的方式使得我们可以把握源码的主线,而非过度纠结于具体的细节。 2.内核的设计是优美的。内核的地位的特殊性决定着内核的执行效率必须足够高才可以响应目前计算机应用的实时性要求,为此Linux内核使用C语言和汇编的混合编程。但是我们都 知道软件执行效率和软件的可维护性很多情况下是背道而驰的。如何在保证内核高效的前提下提高内核的可维护性,这需要依赖于内核中那些“优美”的设计。 3.神奇的编程技巧。在一般的应用软件设计领域,编码的地位可能不被过度的重视,因为开发者更注重软件的良好设计,而编码仅仅是实现手段问题——就像拿斧子劈柴一样,不用太多的思考。但是这在内核中并不成立,好的编码设计带来的不光是可维护性的提高,甚至是代码性能的提升。 每个人对内核的了理解都会有所不同,随着我们对内核理解的不断加深,对其设计和实现的思想会有更多的思考和体会。因此本文更期望于引导更多徘徊在Linux内核大门之外的人进入Linux的世界,去亲自体会内核的神奇与伟大。而我也并非内核源码方面的专家,这么做也只是希望分享我自己的分析源码的经验和心得,为那些需要的人提供参考和帮助,说的“冠冕堂皇”一点,也算是为计算机这个行业,尤其是在操作系统内核方面贡献自己的一份绵薄之力。闲话少叙(已经罗嗦了很多了,囧~),下面我就来分享一下自己的Linix内核源码分析方法。 二、内核源码难不难? 从本质上讲,分析Linux内核代码和看别人的代码没有什么两样,因为摆在你面前的一般都不是你自己写出来的代码。我们先举一个简单的例子,一个陌生人随便给你一个程序,并要你看完源码后讲解一下程序的功能的设计,我想很多自我感觉编程能力还可以的人肯定觉得这没什么,只要我耐心的把他的代码从头到尾看完,肯定能找到答案,并且事实确实是如此。那么现在换一个假设,如果这个人是Linus,给你的就是Linux内核的一个模块的代码,你还会觉得依然那么 轻松吗?不少人可能会有所犹豫。同样是陌生人(Linus要是认识你的话当然不算,呵呵~)给 你的代码,为什么给我们的感觉大相径庭呢?我觉得有以下原因:

linux开机进入命令行模式

Linux默认启动后进入XWindow,但可以修改参数直接进入命令行界面。到底是进入XWindow还是进入命令行界面,是在系统初始化进行的。 对于大部分linux系统,初始化使用init进程,/etc/inittab 为其配置文件。例如 # The default runlevel id:2:initdefault # Boot-time system configuration/initialization script si::sysinit:/etc/init.d/rcS # Runlevels l0:0:wait:/etc/init.d/rc 0 l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 z6:6:respawn:/sbin/sulogin # How to react to ctrl-alt-del ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now 这些内容的通用格式为id:runlevels:action:process。id 是惟一标识该项的字符序列。

runlevels 定义了操作所使用的运行级别。action 指定了要执行的特定操作。process 定义了要执行的进程。 # 对各个运行级的详细解释: 0 为停机,机器关闭。 1 为单用户模式,就像Win9x下的安全模式类似。 2 为多用户模式,但是没有NFS支持。 3 为完整的多用户模式,是标准的运行级。 4 一般不用,在一些特殊情况下可以用它来做一些事情。例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置。 5 就是X11,进到X Window系统了。 6 为重启,运行init 6机器就会重启。 XWindow是init5,字符是init3。将id设置为runlevel设置为3,就可以直接在系统初始化的时候直接进入文本界面。 但Ubuntu并没有采用init的方法,并没有/etc/inittab这个文件。init使用的是串行的方式,引导很耗时。RedHat9启动时串行执行大量的脚本以启动各种需要的服务(启动时可以看到)。Ubuntu采用了upstart,是一个基于事件的init 的替代程序,用于Ubuntu 发行版。Ubuntu中没有/etc/inittab这个文件,但用户可以自己添加。当系统中有/etc/inittab 时Ubuntu会按照配置来启动。 所以要想直接进命令行,第一种方法是用户添加/etc/inittab,不过Debian或是Ubuntu中默认run level是2,且2~5都是指X环境。(但命令行是几?不确定,尚未测试)

相关文档
最新文档