• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            Linux下GetModuleFileName的四種寫法

            Posted on 2011-01-04 23:09 S.l.e!ep.¢% 閱讀(2925) 評論(0)  編輯 收藏 引用 所屬分類: Unix

            Linux下GetModuleFileName的四種寫法

            ? 資料來源:? 點擊: 0

            ??? 資料提示:

            Linux下GetModuleFileName的四種寫法

              問題的起因是要把一個東東從Windows移植到基于Linux的嵌入式系統上。移植過程中,遇到了GetModuleFileName的問題。為了解決這個問題,花了不少的時間,也走了不少彎路。下面是整理的結果。

              首先摘錄一段文字,來源《UNIX Programming FAQ 中文版》
            ?
            1.14. 我怎樣找到進程的相應可執行文件?
              這個問題可以作為常見未回答問題(Frequently Unanswered Questions)的一個好候選,因為事實上提出這個問題經常意味著程序的設計有缺陷。:)
              你能作的最佳猜測(best guess)是通過審視argv[0]的值而獲得。如果它包括一個/,那么它可能是可執行程序的絕對或相對(對于在程序開始時的當前目錄而言)路徑。如果不包括,那么你可以仿效shell對于PATH變量的查詢來查找這個程序。但是,不能保證成功,因為有可能執行程序時argv[0]是一些任意值,也不排除這個可執行文件在執行后可能已經被更名或刪除的情況。
              如果所有你想做的只是能打印一個和錯誤消息一起出現的合適的名字,那么最好的方法在main()函數中將argv[0]的值保存在全局變量中以供整個程序使用。雖然沒有保證說argv[0]的值總是有意義,但在大多數情況下它是最好的選擇。
              人們詢問這個問題的最普通原因是意圖定位他們程序的配置文件。這被認為是不好的形式;包含可執行文件的目錄應當*只*包含可執行文件,而且基于管理的要求經常試圖將配置文件放置在和可執行文件不同的文件系統。
              試圖做這個的一個比較不普通但更正規的理由是允許程序調用exec()執行它自己;這是一種用來完全重新初始化進程(比如被用于一些sendmail的版本)的辦法(比如當一個守護程序捕獲一個SIGHUP信號)。

              完全同意上面的觀點的!所以并不建議在Linux下去實現GetModuleFileName,不過出于技術的角度,討論一下這個問題也是可以的。
            ?
              好,下面說說茴字的四種寫法。哦,不,是GetModuleFileName的四種寫法。


            GetModuleFileName的四種寫法

            方法一:從PATH入手
            說明:上文提供的思路

            int GetModuleFileName1( char* sModuleName, char* sFileName, int nSize)
            {
            ?int ret = -1;
            ?if( strchr( sModuleName,/ ) != NULL )
            ??strcpy( sFileName, sModuleName );
            ?else
            ?{
            ??char* sPath = getenv("PATH");
            ??char* pHead = sPath;
            ??char* pTail = NULL;
            ??while( pHead != NULL && *pHead != \x0 )
            ??{
            ???pTail = strchr( pHead, : );
            ???if( pTail != NULL )
            ???{
            ????strncpy( sFileName, pHead, pTail-pHead );
            ????sFileName[pTail-pHead] = \x0;
            ????pHead = pTail+1;
            ???}
            ???else
            ???{
            ????strcpy( sFileName, pHead );
            ????pHead = NULL;
            ???}
            ???
            ???int nLen = strlen(sFileName);
            ???if( sFileName[nLen] != / )sFileName[nLen] = /;
            ???strcpy( sFileName+nLen+1,sModuleName);
            ???if( 0 == access( sFileName, F_OK ) )
            ???{
            ????ret = 0;
            ????break;
            ???}
            ??}
            ?}
            ?return ret;
            }

            方法二:利用which命令
            說明:? 與方法一相比,完全是換湯不換藥,之所以放在這里,是因為其中用到了一個小技巧:即利用popen()實現在代碼中執行一段command,并得到其執行的結果。
            ???????
            int GetModuleFileName2( char* sModuleName, char* sFileName, int nSize)
            {
            ?int ret = 0;
            ?if( strchr( sModuleName,/ ) != NULL )
            ??strcpy( sFileName, sModuleName );
            ?else
            ?{
            ??char sBuffer[256] = { 0, };
            ??char sCommand[256] = { 0, };
            ??FILE* fp = NULL;
            ??sprintf( sCommand, "which %s", sModuleName );
            ??if((fp = popen(sCommand,"r")) == NULL){
            ???ret = -1;
            ??}???
            ??else
            ??{
            ???sFileName[0] = \x0;
            ???while(!feof(fp)){
            ????if(fgets(sBuffer,nSize-1,fp) == NULL){
            ?????continue;
            ????}
            ????strcat( sFileName, sBuffer );
            ???}
            ??}
            ???? int nLen = strlen( sFileName );
            ??if( 0 == nLen )
            ???ret = -1;
            ??else
            ???if( sFileName[nLen-1] = \n ) sFileName[nLen-1] = \x0;
            ?}
            ?return ret;
            }

            方法二:獲取環境變量"_"

            int GetModuleFileName3( char* sModuleName, char* sFileName, int nSize)
            {
            ?int ret = -1;
            ??? char* p = getenv("_");
            ?if( p != NULL && strstr( p, sModuleName ) != NULL )
            ?{
            ??ret = 0;
            ??strcpy( sFileName, p );
            ?}
            ?return ret;
            }

            方法四:讀取/proc/self/maps
            說明:? 細節請參閱 http://autopackage.org/docs/binreloc/
            int GetModuleFileName4( char* sModuleName, char* sFileName, int nSize)
            {
            ?int ret = -1;
            ?char sLine[1024] = { 0 };
            ?void* pSymbol = (void*)"";
            ?FILE *fp;
            ?char *pPath;

            ?fp = fopen ("/proc/self/maps", "r");
            ?if ( fp != NULL )
            ?{
            ??while (!feof (fp))
            ??{
            ???unsigned long start, end;

            ???if ( !fgets (sLine, sizeof (sLine), fp))
            ????continue;
            ???if ( !strstr (sLine, " r-xp ") || !strchr (sLine, /))
            ????continue;

            ???sscanf (sLine, "%lx-%lx ", &start, &end);
            ???if (pSymbol >= (void *) start && pSymbol < (void *) end)
            ???{
            ????char *tmp;
            ????size_t len;

            ????/* Extract the filename; it is always an absolute path */
            ????pPath = strchr (sLine, /);

            ????/* Get rid of the newline */
            ????tmp = strrchr (pPath, \n);
            ????if (tmp) *tmp = 0;

            ????/* Get rid of "(deleted)" */
            ????//len = strlen (pPath);
            ????//if (len > 10 && strcmp (pPath + len - 10, " (deleted)") == 0)
            ????//{
            ????//?tmp = pPath + len - 10;
            ????//?*tmp = 0;
            ????//}
            ????ret = 0;
            ????strcpy( sFileName, pPath );
            ???}
            ??}
            ??fclose (fp);
            ??
            ?}
            ?return ret;
            }

            測試代碼:

            int main ( int argc, char** argv ) {
            ?char buffer[256]={0};
            ?getchar();
            ?printf ("ModuleFileName1 is: %s\n", GetModuleFileName1( argv[0], buffer, 256)==-1?"Not found!":buffer);
            ?printf ("ModuleFileName2 is: %s\n", GetModuleFileName2( argv[0], buffer, 256)==-1?"Not found!":buffer);
            ?printf ("ModuleFileName3 is: %s\n", GetModuleFileName3( argv[0], buffer, 256)==-1?"Not found!":buffer);
            ?printf ("ModuleFileName4 is: %s\n", GetModuleFileName4( argv[0], buffer, 256)==-1?"Not found!":buffer);
            ?return 0;
            }


            測試結果:

            正常輸出結果:
            ModuleFileName1 is: /home/coldcrane/bin/hello
            ModuleFileName2 is: /home/coldcrane/bin/hello
            ModuleFileName3 is: /home/coldcrane/bin/hello
            ModuleFileName4 is: /home/coldcrane/bin/hello

            程序執行時目錄被移動
            $ mv ~/bin ~/nib
            輸出結果:
            ModuleFileName1 is: Not found!
            ModuleFileName2 is: Not found!
            ModuleFil

            久久国产影院| 久久久久国产一级毛片高清版| 99久久99这里只有免费费精品 | 91精品国产综合久久婷婷| 综合久久给合久久狠狠狠97色| 久久久久久久综合日本| 国产AV影片久久久久久| 91亚洲国产成人久久精品| 久久夜色精品国产| 青青久久精品国产免费看| 久久久久亚洲av毛片大| 久久久一本精品99久久精品88| 亚洲国产精品无码久久| 久久夜色撩人精品国产小说| 欧美精品丝袜久久久中文字幕| 久久久亚洲AV波多野结衣| 免费久久人人爽人人爽av| 无码超乳爆乳中文字幕久久| 久久国产高潮流白浆免费观看| 国产一级持黄大片99久久| 91久久福利国产成人精品| 亚洲国产精品无码久久九九| 久久天天躁狠狠躁夜夜网站| 精品久久久久香蕉网| 久久精品18| 伊人久久大香线蕉亚洲| 国产激情久久久久久熟女老人| 久久人人爽爽爽人久久久| 久久精品www| 日韩欧美亚洲综合久久| 国产精品久久久久aaaa| 亚洲а∨天堂久久精品9966| 人妻无码久久一区二区三区免费 | 日本强好片久久久久久AAA| 国产精品久久久久久| 人人狠狠综合久久亚洲| 国产精品一久久香蕉国产线看观看 | 久久www免费人成精品香蕉| 午夜人妻久久久久久久久| 久久综合狠狠综合久久97色| 亚洲女久久久噜噜噜熟女|