首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ARM Linux 进程调度(3)

ARM Linux 进程调度(3)

switch_mm中是进行页表的切换,即将下一个的pgd的开始物理地址放入CP15中的C2
寄存器。进程的pgd的虚拟地址存放在task_struct结构中的pgd指针中,通过
__virt_to_phys宏可以转变成成物理地址。


static inline void
switch_mm(struct mm_struct *prev, struct mm_struct *next,
         struct task_struct *tsk, unsigned int cpu)
{
       if (prev != next)
              cpu_switch_mm(next->pgd, tsk);
}
 
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)
))
 
#define cpu_get_pgd()      \
       ({                                        \
              unsigned long pg;                     \
              __asm__("mrc p15, 0, %0, c2, c0, 0"      \
                      : "=r" (pg));                \
              pg &= ~0x3fff;                           \
              (pgd_t *)phys_to_virt(pg);         \
       })
 


switch_to()完成进程上下文的切换,通过调用汇编函数__switch_to
完成,其实现比较简单,也就是保存prev进程的上下文信息,该上下文信息由
context_save_struct结构描述,包括主要的寄存器,然后将next
的上下文信息读出,信息保存在task_struct中的thread.save中TSS_SAVE标识了thread.
save在task_struct中的位置。


/*
 * Register switch for ARMv3 and ARMv4 processors
 * r0 = previous, r1 = next, return previous.
 * previous and next are guaranteed not to be the same.
 */
ENTRY(__switch_to)
              stmfd      sp!, {r4 - sl, fp, lr}        @ Store most regs on
stack
              mrs ip, cpsr
              str   ip, [sp, #-4]!                 @ Save cpsr_SVC
              str   sp, [r0, #TSS_SAVE]         @ Save sp_SVC
              ldr   sp, [r1, #TSS_SAVE]         @ Get saved sp_SVC
              ldr   r2, [r1, #TSS_DOMAIN]
 

51 c8051f(f020,f040) msp430 arm(2410,2510) fpga(xc3s4000) dsp(5116 dm642) keilc vc++ matlab linux protel Ten_layerPCB mpegx h.26x Rscode Turbocode ofdm VideoBroadcasting ldpc_code(now!)
/*
* Returns amount of memory which needs to be reserved.
*/


long ed_init(long mem_start, int mem_end)
{
int i,
ep;

short tshort,
version,
length,
s_ofs;

if (register_blkdev(EPROM_MAJOR,"ed",&ed_fops)) {
printk("EPROMDISK: Unable to get major %d.\n", EPROM_MAJOR);
return 0;
}
blk_dev[EPROM_MAJOR].request_fn = DEVICE_REQUEST;

for(i=0;i< 4) {
printk("EPROMDISK: Length (%d) Too short.\n", length);
return 0;
}

ed_length = length * 512;
sector_map = ep + 6;
sector_offset = ep + s_ofs;

printk("EPROMDISK: Version %d installed, %d bytes\n", (int)version, ed_length);
return 0;
}


int get_edisk(unsigned char *buf, int sect, int num_sect)
{
short ss, /* Sector start */
tshort;
int s; /* Sector offset */

for(s=0;s0;) {
sock = bp / EPROM_SIZE;
page = (bp % EPROM_SIZE) / EPAGE_SIZE;
offset = bp % EPAGE_SIZE;

nb = (len+offset)>EPAGE_SIZE?EPAGE_SIZE-(offset%EPAGE_SIZE):len;

cr1 = socket[sock] | ((page << 4) & 0x30) | 0x40; /* no board select for now */
cr2 = (page >> 2) & 0x03;
outb((char)cr1,CONTROL_REG1);
outb((char)cr2,CONTROL_REG2);

memcpy(buf+bofs,(char *)(EPROM_WINDOW + offset),nb);

len -= nb;
bp += nb;
bofs += nb;
}
return 0;
}

med.c代码如下:
/* med.c - make eprom disk image from ramdisk image */

#include
#include
#include
#define DISK_SIZE (6291456)
#define NUM_SECT (DISK_SIZE/512)

void write_eprom_image(FILE *fi, FILE *fo);

int main(int ac, char **av)
{
FILE *fi,
*fo;

char fin[44],
fon[44];

if (ac > 1) {
strcpy(fin,av[1]);
} else {
strcpy(fin,"hda3.ram");
}

if (ac > 2) {
strcpy(fon,av[2]);
} else {
strcpy(fon,"hda3.eprom");
}

fi = fopen(fin,"r");
fo = fopen(fon,"w");

if (fi == 0 || fo == 0) {
printf("Can't open files\n");
exit(0);
}

write_eprom_image(fi,fo);

fclose(fi);
fclose(fo);
}

void write_eprom_image(FILE *fi, FILE *fo)
{
char *ini;
char *outi; /* In and out images */
short *smap; /* Sector map */
char *sp;
char c = 0;

struct {
unsigned short version;
unsigned short blocks;
unsigned short sect_ofs;
} hdr;

int ns,
s,
i,
fs;

ini = (char *)malloc(DISK_SIZE); /* Max disk size is currently 6M */
outi = (char *)malloc(DISK_SIZE); /* Max disk size is currently 6M */
smap = (short *)malloc(NUM_SECT*sizeof(short));

if (ini == NULL || outi == NULL || smap == NULL) {
printf("Can't allocate memory \n");
exit(0);
}

if (DISK_SIZE != fread(ini,1,DISK_SIZE,fi)) {
printf("Can't read input file \n");
exit(0);
}

memcpy(outi,ini,512); /* Copy in first sector */
smap[0] = 0;
ns = 1; /* Number of sectors in outi */

for(i=1;i






















参考书目:
[1]《GNU/Linux编程指南》 (美)K.Wall,M.Watson 清华大学出版社 1999
[2] 《Linux实用指南》 (美)诺顿、格蕾菲斯著 翟大昆等译 机械工业出版社 1999
[3]《嵌入式系統 -- 使用 C 与 C++》 Michael Barr 美商欧莱礼 1999
[4] 《LINUX操作指南》 本社 人民邮电出版社 1999
[5] 《Linux 实用大全》 杨文志编著 北京清华大学出版社 1999
[6] 《单片机与嵌入式系统应用》 何立民 北京航空航天大学出版社 1999
[7] 《Linux内核源代码分析》 (美)马克斯韦尔 机械工业出版社 2000
[8] 《UNIX操作系统设计与实现》 陈华瑛、李建国 电子工业出版社出版 1999

参考文献:
[1]《frambuffer howto》 Geert Uytterhoeven www.linuxdoc.org 1998
[2] 《RTAI Beginner Guide》Emanuele Bianchi www.rtai.org
[3] 《Booting Linux from EPROM》 Dave Bennett www.linuxjournal.com
[4]《ramdiskhowto》 Paul Gortmaker www.linuxdoc.org 1995
[5]《kernelhowto》 Juan-Mariano de Goyeneche www.linuxdoc.org 2000
[6] 《Embedded Linux Howto》 Sebastien Huet www.linux-embedded.com 2000
[7]《lilohowto》 m.skoric www.linuxdoc.org 2001
[8]《linux from scratch howto》 Gerard Beekmans www.linux-embedded.com 2000
[9]《glibc2howto》 Eric Green www.linux.com 1998
[10] 《Kernel Jorn》Alessandro Rubini & Georg Zezchwitz 《Linux Journal》1996
[11]《rtlinux doc》 Michael Barabanov www.rtlinux.com 2001
[12]《the linux boot disk howto》 Tom Fawcett www.linux-embedded.com 2000
51 c8051f(f020,f040) msp430 arm(2410,2510) fpga(xc3s4000) dsp(5116 dm642) keilc vc++ matlab linux protel Ten_layerPCB mpegx h.26x Rscode Turbocode ofdm VideoBroadcasting ldpc_code(now!)
返回列表