mmap和fault handler
      2017-02-24
    
    1. 问题引入
我们想知道, 通过mmap映射文件, 然后读取, 是如何读取到文件的, 其中的fault handler相关的内容.
2. ftrace
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define MEMSIZE 1024*4
#define MPFILE "./.ash_history"
//#define ON_OFF //tracing_on
void write_ftrace(char *path, char *val)
{
    char ftrace_d[50]="/sys/kernel/debug/tracing/";
    int len_d=strlen(ftrace_d);
    int fd_trace=open(strcat(ftrace_d,path), O_RDWR|O_TRUNC);
    if (fd_trace < 0) {
        printf("open %s:%s\n",path,strerror(errno));
        exit(1);
    }
    printf("to write:%s %s\n",path,val);
    int ret=write(fd_trace, val, strlen(val));
    if(ret<0)
    {
        printf("write %s %s\n",path,strerror(errno));
        exit(1);
    }
    if (0==strncmp("trace",path, sizeof("trace")))
    {
        close(fd_trace);
        return;
    }
    char val_read[20];
    memset(val_read,0,sizeof(val_read));
    pread(fd_trace, val_read, sizeof(val_read),0);
    printf("read val:%s\n",val_read);
    close(fd_trace);
}
void write_val(char *path, char *val)
{
    int fd=open(path, O_RDWR);
    if (fd < 0) {
        printf("open %s:%s\n",path,strerror(errno));
        exit(1);
    }
    printf("to write:%s %s\n",path, val);
    int ret=write(fd, val, strlen(val));
    if(ret<0)
    {
        printf("write %s %s\n",path,strerror(errno));
        exit(1);
    }
    char val_read[20];
    memset(val_read,0,sizeof(val_read));
    pread(fd, val_read, sizeof(val_read),0);
    printf("read val:%s\n",val_read);
    close(fd);
}
int main()
{
    char *ptr;
    int fd;
    int ret=-1;
    int i=-1;
    fd = open(MPFILE, O_RDWR);
    if (fd < 0) {
        perror("open()");
        exit(1);
    }
    ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (ptr == NULL) {
        perror("malloc()");
        exit(1);
    }
    /*避免page cache干扰*/
    if( posix_fadvise(fd,0,4096,POSIX_FADV_DONTNEED) != 0) {  
        printf("Cache FADV_DONTNEED failed, %s\n",strerror(errno));  
    }  
    else {  
        printf("Cache FADV_DONTNEED done\n");  
    }  
    //mount -t debugfs nodev /sys/kernel/debug/
    system("mount -t debugfs nodev /sys/kernel/debug/");
    /*
    ~ # echo 1 > /proc/sys/kernel/ftrace_enabled
    */
    write_val("/proc/sys/kernel/ftrace_enabled", "1");
    int pid_cur=getpid();
    printf("pid:%d\n",pid_cur);
    char str_pid[25];
    memset(str_pid,0, sizeof(str_pid));
    snprintf(str_pid, sizeof(str_pid),"%d", pid_cur);
    //  /sys/kernel/debug/tracing/set_ftrace_pid
    write_ftrace("set_ftrace_pid", str_pid);
    write_ftrace("tracing_on", "1");
    /*# can set other filtering here
    echo function > ${ROOT_FTRACE}/current_tracer
    */
    write_ftrace("current_tracer", "function");
    write_ftrace("trace", "0");
    /*
    #echo 0 > ${ROOT_FTRACE}/trace
    echo start_trace_marker > ${ROOT_FTRACE}/trace_marker
    exec $* 
    */
    //write_ftrace("trace_marker", "start_trace_marker");
   i=*ptr;  //这个就是我们要跟踪的
    /*
    echo end_trace_marker > ${ROOT_FTRACE}/trace_marker
    echo 0  > ${ROOT_FTRACE}/tracing_on  #stop record to buffer
    */
    //write_ftrace("trace_marker", "end_trace_marker");
    write_ftrace("tracing_on", "0");
    system("cat /sys/kernel/debug/tracing/trace > mmap.ftrace");
    printf("%x\n", i);
    munmap(ptr, MEMSIZE);
    close(fd);
    exit(1);
}
3. 结果分析
ARM平台, linux-3.10.86, ftrace输出中有:
do_DataAbort <-__dabt_usr
do_page_fault <-do_DataAbort
down_read_trylock <-do_page_fault
_raw_spin_lock_irqsave <-__down_read_trylock
_raw_spin_unlock_irqrestore <-__down_read_trylock
find_vma <-do_page_fault
handle_mm_fault <-do_page_fault
handle_pte_fault <-handle_mm_fault
__do_fault <-handle_pte_fault
filemap_fault <-__do_fault
find_get_page <-filemap_fault
分析: 略
本文地址: https://awakening-fong.github.io/posts/mm/mmap_fault
转载请注明出处: https://awakening-fong.github.io
若无法评论, 请打开JavaScript, 并通过proxy.
blog comments powered by Disqus