<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        gdb+gdbserver調試arm-linux程序

        作者:龔平   來源:本站原創   點擊數:  更新時間:2014年03月14日   【字體:

        mmap作為struct file_operations的重要一個元素,mmap主要是實現物理內存到虛擬內存的映射關系,這樣可以實現直接訪問虛擬內存,而不用使用設備相關的read、write操作,mmap的基本過程是將文件映射到虛擬內存中。在之前的一篇博客中談到了mmap實現文件復制的操作。
        關于linux中的mmap調用如下,最好的辦法查看命令,man mmap:
        必要的頭文件
        #include<sys/mman.h>
        函數聲明
        void * mmap(void *addr,size_t length,int prot,
                 int flags,int fd,off_t offset);
         
        關于各個參數的意義如下:
        1、返回值是一個通用型指針,這樣就保證了各種類型的申請方式。
        2、void *addr 是程序員所希望的虛擬地址作為起始映射地址,通常為NULL,內核自動分配。
        3、size_t length當然是指需要映射的區域大小。
        4、int flags是指對這段區域的保護方式。具體的可以參看內核源碼的linux/mm.h。常用的是PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE。
        5、int flags主要是指對這段區域的映射方式,主要分為兩種方式MAP_SHARE,MAP_PRIVATE.其中的MAP_SHARE是指對映射區域的寫操作會更新到文件中,這樣就相當于直接操作文件。而MAP_PRIVATE通常采用一種稱為"寫時保護的機制"實現映射,對映射區的寫操作不會更新到文件中,實現方法是將需要被寫操作的頁復制到重新分配的新頁中,然后再對新的頁進行寫操作。原來的映射并沒有改變,但是讀操作并不會重新分配物理內存空間。具體的參考深入理解計算機系統。
        6、int fd是指將被映射的文件描述符,映射需要保證文件描述符的正確性。
        7、off_t offset是指從文件的具體位置開始映射,通常情況下可以設置為0,即從開頭映射。
        基本的映射關系如下圖:
         
         
        設備驅動的mmap實現主要是將一個物理設備的可操作區域(設備空間)映射到一個進程的虛擬地址空間。這樣就可以直接采用指針的方式像訪問內存的方式訪問設備。在驅動中的mmap實現主要是完成一件事,就是實際物理設備的操作區域到進程虛擬空間地址的映射過程。同時也需要保證這段映射的虛擬存儲器區域不會被進程當做一般的空間使用,因此需要添加一系列的保護方式。
         
        具體的實現過程如下:

            /*主要是建立虛擬地址到物理地址的頁表關系,其他的過程又內核自己完成*/
            static int mem_mmap(struct file* filp,struct vm_area_struct *vma)
            {
                /*間接的控制設備*/
                struct mem_dev *dev = filp->private_data;
               
                /*標記這段虛擬內存映射為IO區域,并阻止系統將該區域包含在進程的存放轉存中*/
                vma->vm_flags |= VM_IO;
                /*標記這段區域不能被換出*/
                vma->vm_flags |= VM_RESERVED;

                /**/
                if(remap_pfn_range(vma,/*虛擬內存區域*/
                    vma->vm_start, /*虛擬地址的起始地址*/
                    virt_to_phys(dev->data)>>PAGE_SHIFT, /*物理存儲區的物理頁號*/
                 dev->size,    /*映射區域大小*/       
                    vma->vm_page_prot /*虛擬區域保護屬性*/   
                    ))
                    return -EAGAIN;

                return 0;
            }

        具體的實現分析如下:

            vma->vm_flags |= VM_IO;
            vma->vm_flags |= VM_RESERVED;

        上面的兩個保護機制就說明了被映射的這段區域具有映射IO的相似性,同時保證這段區域不能隨便的換出。就是建立一個物理頁與虛擬頁之間的關聯性。具體原理是虛擬頁和物理頁之間是以頁表的方式關聯起來,虛擬內存通常大于物理內存,在使用過程中虛擬頁通過頁表關聯一切對應的物理頁,當物理頁不夠時,會選擇性的犧牲一些頁,也就是將物理頁與虛擬頁之間切斷,重現關聯其他的虛擬頁,保證物理內存夠用。在設備驅動中應該具體的虛擬頁和物理頁之間的關系應該是長期的,應該保護起來,不能隨便被別的虛擬頁所替換。具體也可參看關于虛擬存儲器的文章。

        接下來就是建立物理頁與虛擬頁之間的關系,即采用函數remap_pfn_range(),具體的參數如下:

        int remap_pfn_range(structvm_area_struct *vma, unsigned long addr,unsigned long pfn, unsigned long size, pgprot_t prot)

        1、struct vm_area_struct是一個虛擬內存區域結構體,表示虛擬存儲器中的一個內存區域。其中的元素vm_start是指虛擬存儲器中的起始地址。

        2、addr也就是虛擬存儲器中的起始地址,通?梢赃x擇addr = vma->vm_start。

        3、pfn是指物理存儲器的具體頁號,通常通過物理地址得到對應的物理頁號,具體采用virt_to_phys(dev->data)>>PAGE_SHIFT.首先將虛擬內存轉換到物理內存,然后得到頁號。>>PAGE_SHIFT通常為12,這是因為每一頁的大小剛好是4K,這樣右移12相當于除以4096,得到頁號。

        4、size區域大小

        5、區域保護機制。

        返回值,如果成功返回0,否則正數。

        測試代碼可以直接通過對虛擬內存區域操作,實現不同的操作,如下:

            #include<fcntl.h>
            #include<unistd.h>
            #include<stdio.h>
            #include<stdlib.h>
            #include<sys/types.h>
            #include<sys/stat.h>
            #include<sys/mman.h>
            #include<string.h>

            int main()
            {
                int fd;
                char *start;
                   
                char buf[2048];
                strcpy(buf,"This is a test!!!!");

                fd = open("/dev/memdev0",O_RDWR);
               
                if(fd == -1)
                {
                    printf("Error!!\n");
                    exit(-1);
                }
                /*創建映射*/
                start = mmap(NULL,2048,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
                /*必須檢測是否成功*/
                if(start == -1)
                {
                    printf("mmap error!!!\n");
                    exit(-1);
                }

                strcpy(start,buf);

                printf("start = %s,buf = %s\n",start,buf);

                strcpy(start,"Test is Test!!!\n");

                printf("start = %s,buf = %s\n",start,buf);
                /**/
                strcpy(buf,start);
            
                printf("start = %s,buf=%s\n",start,buf);
                /*取消映射關系*/
                munmap(start,2048);
                /*關閉文件*/
                close(fd);

                exit(0);
            }

        經過測試,成功得到了驅動。

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮