内核中 通过 struct pt_regs 来获取 用户传递的参数 2017-02-23

基于 linux-2.6.35.7/drivers/char/mem.c

#include <asm/ptrace.h>
#include <asm/uaccess.h>

static ssize_t kmsg_write(struct file *file, const char __user *buf,
              size_t count, loff_t *ppos)
{
    char *tmp;
    ssize_t ret;

    tmp = kmalloc(count + 1, GFP_KERNEL);
    if (tmp == NULL)
        return -ENOMEM;
    ret = -EFAULT;
    if (!copy_from_user(tmp, buf, count)) {
        tmp[count] = 0;
        //add
        #define STR_FOUND "sth_will_show_in_dmesg"
        if(NULL!=strstr(tmp,STR_FOUND))
        {
            struct pt_regs *usr_regs; 
            usr_regs=task_pt_regs(current); 
            if(valid_user_regs(usr_regs))
            {
                int fd=usr_regs->ARM_r0;
                char *write_buf=usr_regs->ARM_r1;
                int len=usr_regs->ARM_r2;
                /*用户态程序:
                #define STR_TMP "sth_will_show_in_dmesg"
                int fd=open("/dev/kmsg", O_WRONLY);
                write(fd,STR_TMP,strlen(STR_TMP));
                */

                /*
                内核打印:
                kmsg_write(),969:3 0x6fee0 22
                kmsg_write(),971:buf:sth_will_show_in_dmesg
                也就是打印出了 用户态传递的参数
                */
                tmp_print("%d 0x%x %d",fd,write_buf,len);
                if(access_ok(VERIFY_READ, (void *) write_buf,strlen(write_buf)))
                    tmp_print("buf:%s\n",write_buf);
            }
            else
            {
                tmp_print("not valid_user_regs\n");
            }


        }
        //end add
        ret = printk("%s", tmp);
        if (ret > count)
            /* printk can add a prefix */
            ret = count;
    }
    kfree(tmp);
    return ret;
}

关于THREAD_START_SP 2017-02-23

1. 问题引入

https://awakening-fong.github.io/posts/arm/arm_qemu_02 中说到 startkernel前设置sp为 initthreadunion + THREADSTART_SP

#define THREAD_START_SP (THREAD_SIZE - 8)

为何要-8?

2. 解

static inline struct thread_info *current_thread_info(void)
{
    register unsigned long sp asm ("sp");
    return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}

(图示中A点到B点 大小是8字节)
如果sp是SP0, 那么,(sp & ~(THREADSIZE - 1)) 后还是指向SP0 (A点);
如果sp是SP1, 那么, (sp & ~(THREAD
SIZE - 1)) 后指向的是thread_info (C点).
所以, 需要-8.

IIC相关内容的记忆 2017-02-15

本文的内容 仅仅是为了能够回想起IIC相关内容, 并不求严谨和准确.

1. 起始和停止信号

因为上拉省电, 所以, 空闲时, SDA是上拉的. 在时钟为高时, SDA若表示数据, 需维持稳定, 否则, 其表示起始或停止.

2. 数据的组织 和 表示

假定是7bit地址的情况. 先发送高位还是低位?
可以考虑/回忆下 7bit地址+1bit读写 时的情况, 我们是先发送地址的, 所以, 是先发送高位, 后发送低位的.

最常见的是r/w# 所以,读为1, 写为0.

时钟有, 代表心脏还在跳, 器件还在工作, 所以, 在SCL高电平时对SDA采样作为数据.

page reclaim 04:参数 2017-02-07

未开启CONFIGMEMCG, CONFIGSWAP.

1. scan_control

linux-3.10.86/mm/vmscan.c

struct scan_control {

    /* Incremented by the number of inactive pages that were scanned */
    unsigned long nr_scanned;

    /* How many pages shrink_list() should reclaim 
    问题:nr_to_reclaim和nr_scanned的关系?
    答:nr_to_reclaim是个setting data, nr_reclaimed是runtime date.
    通常是先给struct scan_control sc设置好这个目标, 
    然后启动回收. 
    在 sum of shrink_list() > nr_to_reclaim后中断回收, see shrink_lruvec() or do_try_to_free_pages().
    */
    unsigned long nr_to_reclaim;

    /*
    这里的may类似may I ..., may的意思是 是否可以, 是否允许
    */
    int may_writepage;

    /*
    [Understanding the Linux Kernel, 3rd Edition]p695
    Lower priority implies scanning more pages.
    */
    int priority;

};

get_scan_count
{
        size = get_lru_size(lruvec, lru);
        scan = size >> sc->priority;
        //扫描的量 与 list的大小 成比例
}

shrink_lruvec
|--//1. 根据优先级等 给数组nr[]赋值
|--get_scan_count(lruvec, sc, nr); 

page reclaim 03:活跃度的表示和状态转换 2017-02-07

1. page_referenced

linux-3.10.86/mm/rmap.c

 * Quick test_and_clear_referenced for all mappings to a page,
 * returns the number of ptes which referenced the page.
这个注释过时了, 实际功能并不是返回指向该page的pte的个数. 

 问题:这个函数的用途?
 答:用来反应在inactive list中的page的活跃程度.
 返回数值1和返回数值2是有区别的, see page_check_references
 {
     referenced_ptes = page_referenced(...);
     if (... || referenced_ptes > 1)
        return PAGEREF_ACTIVATE;

 }
 */
int page_referenced(struct page *page,
        int is_locked,
        struct mem_cgroup *memcg,
        unsigned long *vm_flags)