平台移植 – 1 (Cygwin使用淺談)

來源:互聯網
上載者:User

前言 :

最近做的一些工作和平台移植有關, 大致目標是將原來運行在Unix下的一套東西(介面:Cobol, Logic:Cobol, C), 移植到Windows下面(介面:VB.NET, Logic : Cobol, C).

為解決大規模C代碼移植(希望盡量少改寫或不改寫), 先後嘗試了SFU3.5 (on WinXP) 以及Cygwin.

本文主要講解運用Cygwin進行類似代碼移植所遇到的問題以及一些常見的解決方案.

(SFU3.5將在下一篇中簡單介紹.)

 

簡單說明 :

要進行Unix -> Windows 的C代碼移植, 首先考慮到的是MinGW提供的GCC編譯器, 但是很遺憾, 代碼沒有能象我想象中的那麼簡單的就通過編譯了. 原因在於原Unix-C-Source中, 用到了某些特定的系統Function ,如 : shmat(...), shmget(...) etc. (作用大致和共用記憶體相關).

要想在Windows上運行這些Unix系統Function , 可能需要用到Windows下的Posix子系統來真正類比Unix的一整套環境 : 如Login , Shell命令操作, 特定系統Function等. (Posix是一個標準, 主要解決Linux與Unix間的通訊標準等, 可以理解為Linux和Unix必須支援的最小特性集. 在Windows上支援Windows子系統, Posix子系統, 可能還有OS2.  Windows上的Posix子系統即是支援Posix標準, 以便和Unix互動.)

具體的關於Posix子系統的一些講解請參見:

http://archie.ncu.edu.tw/icas/refpage/2b/3b/2b3be9c51fef572b2c8d498ad2bd3713.html

http://www.xemacs.org/Documentation/21.5/html/internals_37.html

既然設計到環境, 就得考慮目前流行的兩種移植平台 : SFU 以及Cygwin. (最後實際採用的是Cygwin, 原因會在SFU的文章中介紹), 下面就具體介紹Cygwin :

Cygwin運行原理大致是 : 核心幾乎完全依賴於Windows子系統的Function, 並在相當於Windows子系統上構建一個Cygwin平台, 這個Cygwin平台提供一些特定的服務,標頭檔(和MinGW一致), Shell命令, 還有特定的Cygwin-GCC etc..  使用Cygwin-GCC編譯的C-Source在入口的時候用由Cygwin進行一些初始化, 使編譯好的應用程式感覺就是在一個Unix平台上運行一樣.

下面介紹我使用Cygwin的全過程 :

1. Cygwin - Install :

    Cygwin據稱全部安裝大約需要4GB空間, 在我進行的工程中並不需要那麼多, 到www.cygwin.com去下載一個安裝程式, 按照下面的步驟安裝:

A. 選擇Download without Installing , download除預設的一些東東, 還需要 : Admin / cygrunsrv, Devel下的GCC, GDB, MinGW等等(幾乎全部)

    cygrunsrv : 包括cygserver服務, 如果Source中用到一些如共用記憶體的, 就需要這個Win-Service.

    Gcc / Gdb : Cygwin下的編譯器及Debugger.

    MinGW : 可能內建開發的IDE, 以及一些標頭檔. (我由於實現安裝了MinGW, 所以沒注意)

B. 下完後, 再運行Installer, 選擇Install, 注意把剛才下的全部選擇安裝.

2. Enviremnt - Setting :

    安裝好後, 注意要設一些東西: (假設你安裝的目錄為C:/Cygwin, 則預設這個目錄為根目錄)

    (另外注意: Cygwin映射Windows盤如: D:/MyWork --> /cygdrive/D/MyWork)

A. 添加C:/Cygwin/bin 到你的環境變數PATH中, 方便使用.

B. 運行 /usr/sbin 下面的cygserver.exe (這裡應該是安裝服務)

    如果安裝好了, 可以用/bin/cygrunsrv 查看服務.

    Eg.

    cygrunsrv -L //列出Cygwin當前啟動並執行所有服務

    cygrunsrv -E cygserver // 停止cygserver服務, 這將導致共用記憶體被清空等一系列操作.

    cygrunsrv -S cygserver // 啟動cygserver 服務, 注意, 只有啟動了這個服務, 共用記憶體等操作才成為可能.

C. 添加 CYGWIN = server 到環境變數中. (MUST)

3. 到此Cygwin基本OK了,可以在CMD中運行bash --login -i 進入Cygwin-Shell, 嘗試ls, rm 等命令確保Cygwin安裝成功. (在Cygwin-Shell裡用GCC嘗試編譯一個HelloWorld, 並確保GCC安裝成功).

 

關於Cygwin的使用, 具體參見 : www.cygwin.com, 裡面有很多FAQ是很多初學者的天堂:)~

 

下面代碼測試Unix-特定Function使用 (注意cygserver要處於運行狀態)

#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/shm.h>

# define DLLEXPORT __declspec (dllexport)  //這裡其實是不需要的, 因為Cygwin-GCC預設匯出所有function.

DLLEXPORT void AllocMemory(int key, const char* str)
...{
    int segment_id;
    char* shared_memory;
    struct shmid_ds shmbuffer;
    int segment_size;
    key_t keys;
    const int shared_segment_size = 0x6400;
 
    printf ("------------- Begin - Alloc Memory-------------- ");

    keys= ftok("/usr", key);

    printf ("1 - keys = %d ", keys);
 
    /**//* Allocate a shared memory segment. */
    //IPC_GET | IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR IPC_STAT
    segment_id = shmget (keys, shared_segment_size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);

    if (segment_id == -1)
    ...{
        printf ("Already alloc memory.  ");
        return;
    }
 
    printf("2 - segment-ID = %d ", segment_id);

    /**//* Attach the shared memory segment. */
    shared_memory = (char*) shmat (segment_id, 0, 0);

    printf ("3 - shared memory at = %p ", shared_memory);

    /**//* Determine the segment’s size. */
    shmctl (segment_id, IPC_STAT, &shmbuffer);
    segment_size = shmbuffer.shm_segsz;
    printf ("4 - Get segment size: %d ", segment_size);

    /**//* Write a string to the shared memory segment. */
    sprintf (shared_memory, str);

    /**//* Detach the shared memory segment. */
    shmdt (shared_memory);

    printf ("5 - share memory : %s. ", str);
    printf ("------------- Over ---------------- ");
}

DLLEXPORT void ReadMemory(int key)
...{
    printf ("------------- Begin - Read Memory-------------- ");

    int segment_id;
    char* shared_memory;
    struct shmid_ds shmbuffer;
    int segment_size;
    key_t keys;
    const int shared_segment_size = 0x6400;
 
    keys= ftok("/usr", key);

    printf ("1 - keys = %d ", keys);

    //return it 
    segment_id = shmget (keys, shared_segment_size, IPC_CREAT);

    if (segment_id == -1)
    ...{
        printf ("Havn't alloc memory yet.  ");
        return;
    }
 
    printf("2 - segment-ID = %d ", segment_id);

    /**//* Attach the shared memory segment. */
    shared_memory = (char*) shmat (segment_id, 0, 0);

    printf ("3 - shared memory at = %p ", shared_memory);

    printf ("4 - shared memory content = %s ", shared_memory);

    printf ("------------- Over ---------------- ");
}

 

用AllocMemory(...) 分配記憶體(注意相同的索引值只能分配一次, 除非cygserver-restart ^_^. ), 用ReadMemory(...)擷取剛才分配的記憶體裡的資料(注意除非cygserver-restart , 否則值是一直存在的, 不會因為運用程式退出而清除)

Cygwin-GCC 編譯的簡單說明:

gcc -shared xxx.c -o xxx.dll //編譯成DLL

gcc -c xxx.c -o xxx.o //編譯成OBJ

gcc xxx.c -o xxx.exe //編譯成EXE

ar r xxx.lib xxx1.o xxx2.o //打包多個obj成一個Lib (非串連)

gcc xxx.c ./L aaa.dll -o xxx.exe //引用外部DLL產生EXE (當然也可以自己寫Def 產生Lib, 再includingLib.)

關於GCC編譯以及MakeFile的簡介會在以後的文章中說明.

------------------ Above Over All ----------------------------------------------------------------------

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.