博文

Linux系统调用宏展开笔记

不知道从哪个版本的内核开始,系统调用变成宏了。在2.6.38的内核里面追踪了一下,以SYSCALL_DEFINE1为例:   SYSCALL_DEFINE1(name,...)展开sys_name,后面的数字,若为1则是一个参数,若为2则为2个参数   具体的宏,展开跟踪流程如下: #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)                                         |                                            v                            #define SYSCALL_DEFINEx(x, sname, ...)              \                                   __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)                         ...

Xen-ARM Guest DOM启动以及VCPU切换

/* 从hypervisor到DOM的转换比较复杂,简单的步骤有两个阶段: 1.将guest的contest的寄存器信息赋值,其中还包括一些DOM设置信息 2.调用scheduler通过__switch_to调度到设置的VCPU上 */ ------------hypervisor------------- construct_guest_dom() { ..... new_thread(v, dsi.v_kernentry, vstack_end, vstartinfo_start); ..... } void new_thread(struct vcpu *d, unsigned long start_pc, unsigned long start_stack, unsigned long start_info) { unsigned long *domain_stack; struct cpu_info *ci; struct cpu_user_regs *domain_context; struct cpu_user_regs *regs = &d->arch.guest_context.user_regs; domain_stack = alloc_xenheap_pages(STACK_ORDER); if(domain_stack == NULL) { return; } ci = (struct cpu_info *)domain_stack; ci->cur_vcpu = d; domain_stack += (STACK_SIZE - sizeof(struct cpu_user_regs))/sizeof(unsigned long); domain_context = (struct cpu_user_regs *)domain_stack; domain_context->r0 = 0; domain_context->r12 = start_info;//参数传过来 domain_context->r13 = start_stack; domain_context->r15 = start_pc;//DOM的启始地址 domain_context->psr = 0x13; regs-...

[xen-arm]关于Goldfish设备初始化

在移植goldfish的时候,如果没有module机制,怎么做呢?从pdev_bus_driver开始.  143 asmlinkage void do_softirq(void) 144 { 145     unsigned int i, cpu = smp_processor_id(); 146     unsigned long pending; 147     pending = softirq_pending(cpu); 148     ASSERT(pending != 0); 149  150     do { 151         i = find_first_set_bit(pending); 152         if(flag < 2 || sched_flag == 1) 153         { 154             if(flag == 0) 155                 switch_init(); 156             local_irq_enable(); 157             if(flag == 1){//设备初始化 158                 goldfish_pdev_bus_driver.probe(&goldfish_pdev_bus_device); 159                 printk("init screen\n"); 160    ...

应用程序在Linux上的执行过程

转自: http://blog.ixpub.net/html/74/13325674-109393.html 执行文件是如何在shell中被"执行"的。本文中尽可能少用一些源码,免得太过于无聊,主要讲清这个过程,感兴趣的同学可以去查看相应的源码了解更多的信息。   1.父进程的行为: 复制,等待 执行应用程序的方式有很多,从shell中执行是一种常见的情况。交互式shell是一个进程(所有的进程都由pid号为1的init进程fork得到,关于这个话题涉及到 Linux 启动和初始化,以及idle进程等,有空再说),当在用户在shell中敲入./test执行程序时,shell先fork()出一个子进程(这也是很多文章中说的子shell),并且wait()这个子进程结束,所以当test执行结束后,又回到了shell等待用户输入(如果创建的是所谓的后台进程,shell则不会等待子进程结束,而直接继续往下执行)。所以shell进程的主要工作是复制一个新的进程,并等待它的结束。   2.子进程的行为: "执行"应用程序 2.1 execve() 另一方面,在子进程中会调用execve()加载test并开始执行。这是test被执行的关键,下面我们详细分析一下。   execve()是操作系统提供的非常重要的一个系统调用,在很多文章中被称为exec()系统调用(注意和shell内部exec命令不一样),其实在Linux中并没有exec()这个系统调用,exec只是用来描述一组函数,它们都以exec开头,分别是:     #include   int execl(const char *path, const char *arg, ...);   int execlp(const char *file, const char *arg, ...);   int execle(const char *path, const char *arg, ..., char *const envp[]);   int execv(const char *path, char *const argv[]);   int execvp(const char *file, char *const ...

怎样向Android社区提交代码

注:[2014-3-13] 向android提交patch的方式已经更新,本文所叙述的方式不再完全匹配,请参考  http://source.android.com/source/submit-patches.html 向开源社区贡献代码的方式很多,Android采用repo的方式。 由于在提交patch的时候,必须使用repo upload命令,所以,首先要安装 repo 在自己的项目中。安装repo在自己项目的步骤分两步: 1-1. $ curl  http://android.git.kernel.org/repo > ~/bin/repo $ chmod a+x ~/bin/repo 1-2.然后把~/bin加入到PATH环境变量中,如果不加的话,用repo就需要全路径,比较麻烦,不管怎样,下面这一步是可选的: $ export PATH=~/bin:$PATH 2.安装repo到自己的项目中,只有安装到自己项目中后,才可以使用repo,即使是repo help也不例外。 $ repo init -u git:// android.git.kernel.org/platform/manifest.git 题外话:使用repo比使用git更麻烦,在教育网中,repo platform几乎是不能完成的任务,当然,可以使用git proxy,不过这种方法并不好使,一个简单且方便的方法是搞一个VPS 。 如果自己要提交的project没有在manifest管辖的范围内,那就需要自己去修改.repo/manifest.xml文件了。 比如,我要修改的Project项目名称是kernel/common,路径是kernel/common,而这个Project并没有在manifest.xml,所以在.repo/mainfest.xml文件中添加这么一行: <project path="kernel/common" name="kernel/common/" /> 然后运行repo sync去下载整个platform,整个platform的容量基本上2GB左右,如果没有必要下载那么多的项目,修改.repo/manifest.xml,只保留自己的...

Android 与Linux Kernel

在kernel子目录下存放的就是Android的Linux Kernel了, 通过和标准的Linux 2.6.25 Kernel的对比,我们可以发现,其主要增加了以下的内容: 1. 基于ARM架构增加Gold-Fish平台,相应增加的目录如下: kernel/arch/arm/mach-goldfish kernel/include/asm-arm/arch-goldfish Gold-Fish平台采用的是ARM926T CPU作为BaseBand处理器, 该CPU主频至少为200M HZ. 采用MSM7201A CPU(ARM 11)作为主CPU, 其主频为528M HZ. 2. 增加了yaffs2 FLASH文件系统,相应增加的目录为: kernel/fs/yaffs2 实际上,Android包经过编译后生成的system.img和ramdisk.img文件就是yaffs2格式的包. 3. 增加了Android的相关Driver,相应目录为: kernel/drivers/android 主要分为: Android IPC系统: Binder Android 日志系统: Logger Android 电源管理: Power Android 闹钟管理: Alarm Android 内存控制台: Ram_console Android 时钟控制的gpio: Timed_gpio 4. 增加了switch处理, 相应的目录为: kernel/drivers/switch/ 5. 增加了一种新的共享内存处理方式, 相应增加的文件为: kernel/mm/ashmem.c 6. 其他为Linux-2.6.25内核所做的补丁等等,例如BlueTooth, 在此不做详细分析 另外GoldFish平台相关的驱动文件如下: 1. 字符输出设备: kernel/drivers/char/goldfish_tty.c 2. 图象显示设备: (Frame Buffer) kernel/drivers/video/goldfishfb.c 3. 键盘输入设备: kernel/drivers/input/keyboard/goldfish_events.c 4. RTC设备: (Real Time Clock) kernel/drivers/rtc/rtc-goldfish.c . US...

Linux进程调度中队列的使用

Linux 进程调度中队列的使用 作者:西邮 王聪 Linux 内核中大量使用了队列,这里仅列举它在进程调度中的几处应用。 Linux 内核中的队列是以双链表的形式连接起来的, include/linux/list.h 中定义了队列并提供了一些接口,详细的介绍可以参考 [1] 中的附录。 Linux 中的进程有如下几个主要状态: 进程状态 说明 TASK_RUNNING 进程正在运行或将要被运行。 TASK_INTERRUPTIBLE 进程正在睡眠,等待某个条件的完成。 TASK_UNINTERRUPTIBLE 深度睡眠,不会被信号打扰。 TASK_STOPPED 进程运行被停止。 TASK_TRACED 进程被调试程序停止,被另一个进程跟踪。 两个额外的状态是 EXIT_ZOMBIE 和 EXIT_DEAD ,表示进程处于僵死状态还是真正死亡。处于僵死状态的进程会等待其父进程的收养(否则就会被 init 进程收养),而真正死亡的进程会被直接删除。 状态为 TASK_RUNNING 的进程都会被放入运行队列( runqueue )中,这是通过 task_struct (定义在 include/linux/sched.h )中的 run_list 成员来链接的。不过,为了让内核每次都能选取优先级最合适的进程, Linux 为每个优先级构建了一个 queue 。这是通过 struct prio_array 来实现的, struct prio_array 的定义在 kernel/sched.c ,大致如下: struct prio_array { int nr_active; unsigned long bitmap[BITMAP_SIZE]; struct list_head queue[MAX_PRIO]; }; queue 成员就是队列数组。每个 CPU 有各自的 runqueue ,每一个 runqueue 又有包含两个 prio_array ,一个是活动队列,一个是时间片耗尽的队列。当运行队列空时,内核便会交换两个队列的指针,原来的耗尽队列就成了新的活动队列!这和 prio_array 中的 bitmap 是决定调度算法为 O(1) 的关键。 状态为 TASK_STOPPED , EXIT_ZOMBIE 或 ...