1. 程式人生 > >Linux下將實體地址對映到使用者空間

Linux下將實體地址對映到使用者空間

/************************************************************/
/* file name : memmap.c                                     */
/* linux /dev/mem mmap support func							*/
/* 															*/
/* 															*/
/* Copyright 2005 huawei com.                               */
/* Author :zhouaidi(42136)									*/
/* Create date: 2005-04-07									*/
/* Modify history											*/
/* 2005-06-12: 對對映成功空間建立管理連結串列,可以防止對重疊   */
/*             空間的重複對映                               */
/* 2005-12-21: 增加memunmap函式                             */
/************************************************************/

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

typedef struct tag_MMAP_Node
{
	unsigned int Start_P;
	unsigned int Start_V;
	unsigned int length;
    unsigned int refcount;  /* map後的空間段的引用計數 */
	struct tag_MMAP_Node * next;
}TMMAP_Node_t;

TMMAP_Node_t * pTMMAPNode = NULL;

#define PAGE_SIZE 0x1000
#define PAGE_SIZE_MASK 0xfffff000

static int fd = -1;
static const char dev[]="/dev/mem";


/* no need considering page_size of 4K */
void * memmap(unsigned int phy_addr, unsigned int size)
{
	unsigned int phy_addr_in_page;
	unsigned int page_diff;

	unsigned int size_in_page;

	TMMAP_Node_t * pTmp;
	TMMAP_Node_t * pNew;
	
	void *addr=NULL;

	if(size == 0)
	{
		printf("memmap():size can't be zero!\n");
		return NULL;
	}

	/* check if the physical memory space have been mmaped */
	pTmp = pTMMAPNode;
	while(pTmp != NULL)
	{
		if( (phy_addr >= pTmp->Start_P) && 
			( (phy_addr + size) <= (pTmp->Start_P + pTmp->length) ) )
		{
            pTmp->refcount++;   /* referrence count increase by 1  */
			return (void *)(pTmp->Start_V + phy_addr - pTmp->Start_P);
		}

		pTmp = pTmp->next;
	}

	/* not mmaped yet */
	if(fd < 0)
	{
		/* dev not opened yet, so open it */
		fd = open (dev, O_RDWR | O_SYNC);
		if (fd < 0)
		{
			printf("memmap():open %s error!\n", dev);
			return NULL;
		}
	}

	/* addr align in page_size(4K) */
	phy_addr_in_page = phy_addr & PAGE_SIZE_MASK;
	page_diff = phy_addr - phy_addr_in_page;

	/* size in page_size */
	size_in_page =((size + page_diff - 1) & PAGE_SIZE_MASK) + PAGE_SIZE;

	addr = mmap ((void *)0, size_in_page, PROT_READ|PROT_WRITE, MAP_SHARED, fd, phy_addr_in_page);
	if (addr == MAP_FAILED)
	{
		printf("memmap():mmap @ 0x%x error!\n", phy_addr_in_page);
		return NULL;
	}

	/* add this mmap to MMAP Node */
	pNew = (TMMAP_Node_t *)malloc(sizeof(TMMAP_Node_t));
    if(NULL == pNew)
    {
        printf("memmap():malloc new node failed!\n");
        return NULL;
    }
	pNew->Start_P = phy_addr_in_page;
	pNew->Start_V = (unsigned int)addr;
	pNew->length = size_in_page;
    pNew->refcount = 1;
	pNew->next = NULL;
	
	if(pTMMAPNode == NULL)
	{
		pTMMAPNode = pNew;
	}
	else
	{
		pTmp = pTMMAPNode;
		while(pTmp->next != NULL)
		{
			pTmp = pTmp->next;
		}

		pTmp->next = pNew;
	}

	return (void *)(addr+page_diff);
}

/*****************************************************************************
 Prototype    : memunmap
 Description  : 
 Input        : void * addr_mapped  
 Output       : None
 Return Value : On success, returns 0, on failure -1 
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2005/12/21
    Author       : Z42136
    Modification : Created function

*****************************************************************************/
int memunmap(void * addr_mapped)
{
	TMMAP_Node_t * pPre;
	TMMAP_Node_t * pTmp;

    if(pTMMAPNode == NULL)
    {
        printf("memunmap(): address have not been mmaped!\n");
        return -1;
    }

	/* check if the physical memory space have been mmaped */
	pTmp = pTMMAPNode;
    pPre = pTMMAPNode;

    do
	{
		if( ((unsigned int)addr_mapped >= pTmp->Start_V) && 
			((unsigned int)addr_mapped <= (pTmp->Start_V + pTmp->length)) )
		{
            pTmp->refcount--;   /* referrence count decrease by 1  */
            if(0 == pTmp->refcount)
            {
                /* 引用計數變為0, 被map的記憶體空間不再使用,此時需要進行munmap回收 */
 
        //        printf("memunmap(): map node will be remove!\n");

                /* delete this map node from pMMAPNode */
                if(pTmp == pTMMAPNode)
                {
                    pTMMAPNode = NULL;
                }
                else
                {
                    pPre->next = pTmp->next;
                }

                /* munmap */
                if(munmap((void *)pTmp->Start_V, pTmp->length) != 0 )
                {
                    printf("memunmap(): munmap failed!\n");
                }

                free(pTmp);
            }
            
            return 0;
		}

        pPre = pTmp;
		pTmp = pTmp->next;
	}while(pTmp != NULL);

    printf("memunmap(): address have not been mmaped!\n");
    return -1;
}

相關推薦

Linux實體地址對映到使用者空間

/************************************************************/ /* file name : memmap.c */ /* linux /d

Linux關閉ALSR(地址空間隨機化)的方法

0x00 背景知識 ASLR(Address Space Layout Randomization)在2005年被引入到Linux的核心 kernel 2.6.12 中,當然早在2004年就以patch的形式被引入。隨著記憶體地址的隨機化,使得響應的應用變得隨機。這意味著同一應用多次

Linux4G虛擬地址空間的分佈

我們現在所寫的原始碼並不是我們所說的程式,從C程式碼(.c/.cpp)---->連結程式(.exe)是要經過以下幾個過程才能真正的執行連結的; C源程式--->預編譯處理(.c/.cpp)-->編譯,優化程式(.s)--->彙編程式(.o)---&g

linux的記憶體實體地址對映地址

1.1  Linux裝置驅動程式對外設I/O端的訪問。  眾所周知幾乎每一種外設都是通過讀寫裝置上的暫存器來進行的,通常包括控制暫存器、狀態暫存器和資料暫存器三大類,外設的暫存器通常被連續地編址。根據CPU體系結構的不同,CPU對IO埠的編址方式有兩種:I/O對映方式和記憶

Linux用戶添加到sudoers中

http his root密碼 配置 not in rep 希望 輸入密碼 -h Linux默認是沒有將用戶添加到sudoers列表中的,需要root手動將賬戶添加到sudoers列表中,才能讓普通賬戶執行sudo命令。 root 賬戶鍵入visudo即可進入sudo配置,

使用windbg在開啟PAE的情況虛擬地址轉化成物理地址

技術分享 dir halt cgroup nbsp session bre dog 格式 在開啟PAE之後,32位的線性地址的結構發生了變化,具體結構如下 30-31位:頁目錄指針表索引 21-29位:頁目錄索引 12-20位:頁表索引 0-11位:頁內偏移 在開啟PAE

單目跟蹤位姿產品研發(二)----在linuxc++工程打包成動態庫so檔案API

       單目跟蹤位姿專案由對方公司提供應用場景,我方研發核心演算法,通過c++實現功能,然後對方公司通過java\js來開發炫酷的介面,共同合作完成,最終對方公司負責銷售推廣,推向市場。因此,涉及到java介面呼叫c++核心程式碼的問題。 現記錄

Linuxtomcat註冊成系統服務

編寫啟動指令碼 vi /etc/rc.d/init.d/tomcat  //需將JAVA_HOME和CAGTALANA_HOME替換成自己的jdk安裝目錄和tomcat安裝目錄 #!/bin/bash # # tomcat startup script for

linuxpdf檔案轉換成swf檔案

用PHP用到了線上瀏覽pdf檔案的功能,js播放外掛需要同時將pdf檔案轉換成swf檔案兩者兼用才能達到效果。 安裝swftools 中文支援安裝: mkdir –p /usr/share/xpdf cd /usr/share/xpdf/ 下載中文支援及字型庫 wget ftp:/

linux檔案設定為swap

在網上弄了一臺VPS,結果安裝完系統發現沒有swap。因為記憶體比較小,沒有swap有時候容易卡死,於是打算設定一個檔案充當swap。以前幹過這事,不過因為一般裝系統時候會設,所以這功能基本用不到,漸漸也就忘了。今天又查了一下,記錄在此備忘。   先建立一個固定大小的檔案 sudo dd if

Linuxoracle資料庫碰到字元亂碼時改成utf8編碼的方法

在Linux下oracle資料庫碰到字元亂碼的解決方法 linux下Oracle顯示中文亂碼的情況和原因 DEPTNO DNAME LOC ---------- -------------- -------------

LinuxMysql和Apache加入到系統服務裡的方法

原文地址 Apache加入到系統服務裡面:    cp /安裝目錄下/apache/bin/apachectl /etc/rc.d/init.d/httpd    修改httpd    在檔案頭部加入如下內容:    ###    # Comments to support

Linux檔案打包、壓縮並分割成指定大小

轉自https://blog.csdn.net/loongembedded/article/details/54233175 Linux解壓檔案時遇到的問題,不知道總的資料是分了好多份,需要輸入命令統一解壓 1、普通tar壓縮命令 tar -zcvf

linux修改IP地址的方法

1. 網絡卡的命名規則 在centos7中,en表示著:ethernet乙太網,即現在所用的區域網,enX(X常見有以下3種類型) 型別 說明 o 主機板板載網絡卡,整合裝置的裝置索引

下載m3u8視訊及在Linuxts合併為mp4格式

背景 在爬取視訊時偶爾會遇見m3u8格式的視訊連結,視訊下載後為多個ts檔案,下面分享如何下載m3u8格式視訊以及在Linux下將ts檔案合成mp4 檔案。 m3u8格式連結解析 url = xxxxx.m3u8 #獲取m3u8檔案的文字資訊 all_content = req

linux一個目錄的所有檔案拷貝到另一個大檔案中,並把大檔案拆分成原來的小檔案,大小,內容,名字不變

經過四五天的編寫與除錯,初步完成了檔案操作工具的內容,以下是程式碼說明: 首先,我測試用的檔案在/home/xudong/mywork下,我的最終生成檔案是在這個路徑下,/home/xudong/work/resultfile.txt,分開後生成的小檔案在/home/xud

Linux網路IP地址的轉換函式 (轉)

網路IP地址本是用32位二進位制來表示的,為了記憶的方便可以用點分十進位制來表示IP地址,同時,網路IP地址在網路傳輸和計算機內部的儲存方式也不同,需要用函式來進行轉換。 1.將點分十進位制字串轉換成十進位制長整型數:in_addr_t inet_addr(const char *cp);       in_

Linux檢視IP地址歸屬地

使用curl命令: curl ip.cn/IP如: curl ip.cn/www.baidu.com IP:14.215.177.38 來自:廣東省廣州市 電信 curl ip.cn/www.z

linux配置ip地址四種方法

本來說這個配置ip地址是很簡單的事情,但是每次都很頭疼,總是找不到網口,中有local一個 現在總結一下,希望以後不要出問題。 我遇到的問題: SUSE11.1_legacy_x64  ,ifconfig->只能看到lo,無法找到其他網絡卡 解決: 1.Compu

linuxPython指令碼打包為可執行檔案

一. 下載pyinstaller 連結 二. 解壓 無需安裝,解壓即可使用 三. 輸入命令,進行打包 命令格式: pyinstaller_path/pyinstaller.py -F s