在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 嵌入式Linux的ARM移植實例研究

            嵌入式Linux的ARM移植實例研究

            作者: 時間:2012-05-16 來源:網(wǎng)絡(luò) 收藏

            應(yīng)用實例的編寫實際上已經(jīng)不屬于操作系統(tǒng)移植的范疇,但是為了保證本系列文章的完整性,這里提供一系列針對嵌入式開發(fā)應(yīng)用程序的實例。

            編寫應(yīng)用程序要用到如下工具:

            (1)編譯器:GCC

            GCC是Linux平臺下最重要的開發(fā)工具,它是GNU的C和C++編譯器,其基本用法為:gcc[options][filenames]。
            我們應(yīng)該使用arm-linux-gcc。

            (2)調(diào)試器:GDB

            gdb是一個用來調(diào)試C和C++程序的強力調(diào)試器,我們能通過它進行一系列調(diào)試工作,包括設(shè)置斷點、觀查變量、單步等。
            我們應(yīng)該使用arm-linux-gdb。

            (3)Make

            GNUMake的主要工作是讀進一個文本文件,稱為makefile。這個文件記錄了哪些文件由哪些文件產(chǎn)生,用什么命令來產(chǎn)生。Make依靠此makefile中的信息檢查磁盤上的文件,如果目的文件的創(chuàng)建或修改時間比它的一個依靠文件舊的話,make就執(zhí)行相應(yīng)的命令,以便更新目的文件。

            Makefile中的編譯規(guī)則要相應(yīng)地使用arm-linux-版本。

            (4)代碼編輯

            可以使用傳統(tǒng)的vi編輯器,但最好采用emacs軟件,它具備語法高亮、版本控制等附帶功能。

            在宿主機上用上述工具完成應(yīng)用程序的開發(fā)后,可以通過如下途徑將程序下載到目標板上運行:

            (1)通過串口通信協(xié)議rz將程序下載到目標板的文件系統(tǒng)中(感謝Linux提供了rz這樣的一個命令);
            (2)通過ftp通信協(xié)議從宿主機上的ftp目錄里將程序下載到目標板的文件系統(tǒng)中;
            (3)將程序拷入U盤,在目標機上mountU盤,運行U盤中的程序;
            (4)如果目標機Linux使用NFS文件系統(tǒng),則可以直接將程序拷入到宿主機相應(yīng)的目錄內(nèi),在目標機Linux中可以直接使用。

            1.文件編程

            Linux的文件操作API涉及到創(chuàng)建、打開、讀寫和關(guān)閉文件。

            創(chuàng)建

            intcreat(constchar*filename,mode_tmode);
            參數(shù)mode指定新建文件的存取權(quán)限,它同umask一起決定文件的最終權(quán)限(modeumask),其中umask代表了文件在創(chuàng)建時需要去掉的一些存取權(quán)限。umask可通過系統(tǒng)調(diào)用umask()來改變:
            intumask(intnewmask);
            該調(diào)用將umask設(shè)置為newmask,然后返回舊的umask,它只影響讀、寫和執(zhí)行權(quán)限。

            打開

            intopen(constchar*pathname,intflags);
            intopen(constchar*pathname,intflags,mode_tmode);

            讀寫

            在文件打開以后,我們才可對文件進行讀寫了,Linux中提供文件讀寫的系統(tǒng)調(diào)用是read、write函數(shù):
            intread(intfd,constvoid*buf,size_tlength);
            intwrite(intfd,constvoid*buf,size_tlength);

            其中參數(shù)buf為指向緩沖區(qū)的指針,length為緩沖區(qū)的大小(以字節(jié)為單位)。函數(shù)read()實現(xiàn)從文件描述符fd所指定的文件中讀取length個字節(jié)到buf所指向的緩沖區(qū)中,返回值為實際讀取的字節(jié)數(shù)。函數(shù)write實現(xiàn)將把length個字節(jié)從buf指向的緩沖區(qū)中寫到文件描述符fd所指向的文件中,返回值為實際寫入的字節(jié)數(shù)。
            以O(shè)_CREAT為標志的open實際上實現(xiàn)了文件創(chuàng)建的功能,因此,下面的函數(shù)等同creat()函數(shù):
            intopen(pathname,O_CREAT|O_WRONLY|O_TRUNC,mode);

            定位

            對于隨機文件,我們可以隨機的指定位置讀寫,使用如下函數(shù)進行定位:
            intlseek(intfd,offset_toffset,intwhence);
            lseek()將文件讀寫指針相對whence移動offset個字節(jié)。操作成功時,返回文件指針相對于文件頭的位置。參數(shù)whence可使用下述值:
            SEEK_SET:相對文件開頭
            SEEK_CUR:相對文件讀寫指針的當(dāng)前位置
            SEEK_END:相對文件末尾
            offset可取負值,例如下述調(diào)用可將文件指針相對當(dāng)前位置向前移動5個字節(jié):
            lseek(fd,-5,SEEK_CUR);
            由于lseek函數(shù)的返回值為文件指針相對于文件頭的位置,因此下列調(diào)用的返回值就是文件的長度:
            lseek(fd,0,SEEK_END);

            關(guān)閉

            只要調(diào)用close就可以了,其中fd是我們要關(guān)閉的文件描述符:
            intclose(intfd);
            下面我們來編寫一個應(yīng)用程序,在當(dāng)前目錄下創(chuàng)建用戶可讀寫文件example.txt,在其中寫入HelloWorld,關(guān)閉文件,再次打開它,讀取其中的內(nèi)容并輸出在屏幕上:
            #include
            #include
            #include
            #include
            #defineLENGTH100
            main()
            {
            intfd,len;
            charstr[LENGTH];
            fd=open(hello.txt,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR);/*創(chuàng)建并打開文件*/
            if(fd)
            {
            write(fd,Hello,SoftwareWeekly,strlen(Hello,softwareweekly));
            /*寫入Hello,softwareweekly字符串*/
            close(fd);
            }
            fd=open(hello.txt,O_RDWR);
            len=read(fd,str,LENGTH);/*讀取文件內(nèi)容*/
            str[len]='';
            printf(%sn,str);
            close(fd);
            }

            2.控制/通信編程

            控制中主要涉及到的創(chuàng)建、睡眠和退出等,在Linux中主要提供了fork、exec、clone的進程創(chuàng)建方法,sleep的進程睡眠和exit的進程退出調(diào)用,另外Linux還提供了父進程等待子進程結(jié)束的系統(tǒng)調(diào)用wait。
            fork
            對于沒有接觸過Unix/Linux操作系統(tǒng)的人來說,fork是最難理解的概念之一,因為它執(zhí)行一次卻返回兩個值,以前聞所未聞。先看下面的程序:
            intmain()
            {
            inti;
            if(fork()==0)
            {
            for(i=1;i3;i++)
            printf(Thisischildprocessn);
            }
            else
            {
            for(i=1;i3;i++)
            printf(Thisisparentprocessn);
            }
            }

            執(zhí)行結(jié)果為:
            Thisischildprocess
            Thisischildprocess
            Thisisparentprocess
            Thisisparentprocess

            fork在英文中是分叉的意思,一個進程在運行中,如果使用了fork,就產(chǎn)生了另一個進程,于是進程就分叉了。當(dāng)前進程為父進程,通過fork()會產(chǎn)生一個子進程。對于父進程,fork函數(shù)返回子程序的進程號而對于子程序,fork函數(shù)則返回零,這就是一個函數(shù)返回兩次的本質(zhì)。

            exec

            在Linux中可使用exec函數(shù)族,包含多個函數(shù)(execl、execlp、execle、execv、execve和execvp),被用于啟動一個指定路徑和文件名的進程。exec函數(shù)族的特點體現(xiàn)在:某進程一旦調(diào)用了exec類函數(shù),正在執(zhí)行的程序就被干掉了,系統(tǒng)把代碼段替換成新的程序(由exec類函數(shù)執(zhí)行)的代碼,并且原有的數(shù)據(jù)段和堆棧段也被廢棄,新的數(shù)據(jù)段與堆棧段被分配,但是進程號卻被保留。也就是說,exec執(zhí)行的結(jié)果為:系統(tǒng)認為正在執(zhí)行的還是原先的進程,但是進程對應(yīng)的程序被替換了。

            fork函數(shù)可以創(chuàng)建一個子進程而當(dāng)前進程不死,如果我們在fork的子進程中調(diào)用exec函數(shù)族就可以實現(xiàn)既讓父進程的代碼執(zhí)行又啟動一個新的指定進程,這很好。fork和exec的搭配巧妙地解決了程序啟動另一程序的執(zhí)行但自己仍繼續(xù)運行的問題,請看下面的例子:
            charcommand[MAX_CMD_LEN];

            voidmain()
            {
            intrtn;/*子進程的返回數(shù)值*/
            while(1)
            {
            /*從終端讀取要執(zhí)行的命令*/
            printf(>);
            fgets(command,MAX_CMD_LEN,stdin);
            command[strlen(command)-1]=0;
            if(fork()==0)
            {
            /*子進程執(zhí)行此命令*/
            execlp(command,command);
            /*如果exec函數(shù)返回,表明沒有正常執(zhí)行命令,打印錯誤信息*/
            perror(command);
            exit(errorno);
            }
            else
            {
            /*父進程,等待子進程結(jié)束,并打印子進程的返回值*/
            wait(rtn);
            printf(childprocessreturn%dn,rtn);
            }
            }
            }
            這個函數(shù)實現(xiàn)了一個shell的功能,它讀取用戶輸入的進程名和參數(shù),并啟動對應(yīng)的進程。

            clone

            clone是Linux2.0以后才具備的新功能,它較fork更強(可認為fork是clone要實現(xiàn)的一部分),可以使得創(chuàng)建的子進程共享父進程的資源,并且要使用此函數(shù)必須在編譯內(nèi)核時設(shè)置clone_actually_works_ok選項。

            clone函數(shù)的原型為:
            intclone(int(*fn)(void*),void*child_stack,intflags,void*arg);
            此函數(shù)返回創(chuàng)建進程的PID,函數(shù)中的flags標志用于設(shè)置創(chuàng)建子進程時的相關(guān)選項。
            來看下面的例子:
            intvariable,fd;
            intdo_something(){
            variable=42;
            close(fd);
            _exit(0);
            }
            intmain(intargc,char*argv[]){
            void**child_stack;
            chartempch;
            variable=9;
            fd=open(test.file,O_RDONLY);
            child_stack=(void**)malloc(16384);
            printf(Thevariablewas%dn,variable);
            clone(do_something,child_stack,CLONE_VM|CLONE_FILES,NULL);
            sleep(1);/*延時以便子進程完成關(guān)閉文件操作、修改變量*/
            printf(Thevariableisnow%dn,variable);
            if(read(fd,tempch,1)1){
            perror(FileReadError);
            exit(1);
            }
            printf(Wecouldreadfromthefilen);
            return0;
            }
            運行輸出:
            Thevariableisnow42
            FileReadError
            程序的輸出結(jié)果告訴我們,子進程將文件關(guān)閉并將變量修改(調(diào)用clone時用到的CLONE_VM、CLONE_FILES標志將使得變量和文件描述符表被共享),父進程隨即就感覺到了,這就是clone的特點。

            sleep

            函數(shù)調(diào)用sleep可以用來使進程掛起指定的秒數(shù),該函數(shù)的原型為:
            unsignedintsleep(unsignedintseconds);
            該函數(shù)調(diào)用使得進程掛起一個指定的時間,如果指定掛起的時間到了,該調(diào)用返回0;如果該函數(shù)調(diào)用被信號所打斷,則返回剩余掛起的時間數(shù)(指定的時間減去已經(jīng)掛起的時間)。

            exit

            系統(tǒng)調(diào)用exit的功能是終止本進程,其函數(shù)原型為:
            void_exit(intstatus);
            _exit會立即終止發(fā)出調(diào)用的進程,所有屬于該進程的文件描述符都關(guān)閉。參數(shù)status作為退出的狀態(tài)值返回父進程,在父進程中通過系統(tǒng)調(diào)用wait可獲得此值。

            wait

            wait系統(tǒng)調(diào)用包括:
            pid_twait(int*status);
            pid_twaitpid(pid_tpid,int*status,intoptions);
            wait的作用為發(fā)出調(diào)用的進程只要有子進程,就睡眠到它們中的一個終止為止;waitpid等待由參數(shù)pid指定的子進程退出。

            Linux的進程間通信(IPC,InterProcessCommunication)通信方法有管道、消息隊列、共享內(nèi)存、信號量、套接口等。套接字通信并不為Linux所專有,在所有提供了TCP/IP協(xié)議棧的操作系統(tǒng)中幾乎都提供了socket,而所有這樣操作系統(tǒng),對套接字的編程方法幾乎是完全一樣的。管道分為有名管道和無名管道,無名管道只能用于親屬進程之間的通信,而有名管道則可用于無親屬關(guān)系的進程之間;消息隊列用于運行于同一臺機器上的進程間通信,與管道相似;共享內(nèi)存通常由一個進程創(chuàng)建,其余進程對這塊內(nèi)存區(qū)進行讀寫;信號量是一個計數(shù)器,它用來記錄對某個資源(如共享內(nèi)存)的存取狀況。

            下面是一個使用信號量的例子,該程序創(chuàng)建一個特定的IPC結(jié)構(gòu)的關(guān)鍵字和一個信號量,建立此信號量的索引,修改索引指向的信號量的值,最后清除信號量:

            #include
            #include
            #include
            #include
            voidmain()
            {
            key_tunique_key;/*定義一個IPC關(guān)鍵字*/
            intid;
            structsembuflock_it;
            unionsemunoptions;
            inti;
            unique_key=ftok(.,'a');/*生成關(guān)鍵字,字符'a'是一個隨機種子*/
            /*創(chuàng)建一個新的信號量集合*/
            id=semget(unique_key,1,IPC_CREAT|IPC_EXCL|0666);
            printf(semaphoreid=%dn,id);
            options.val=1;/*設(shè)置變量值*/
            semctl(id,0,SETVAL,options);/*設(shè)置索引0的信號量*/
            /*打印出信號量的值*/
            i=semctl(id,0,GETVAL,0);
            printf(valueofsemaphoreatindex0is%dn,i);
            /*下面重新設(shè)置信號量*/
            lock_it.sem_num=0;/*設(shè)置哪個信號量*/
            lock_it.sem_op=-1;/*定義操作*/
            lock_it.sem_flg=IPC_NOWAIT;/*操作方式*/
            if(semop(id,lock_it,1)==-1)
            {
            printf(cannotlocksemaphore.n);
            exit(1);
            }
            i=semctl(id,0,GETVAL,0);
            printf(valueofsemaphoreatindex0is%dn,i);
            /*清除信號量*/
            semctl(id,0,IPC_RMID,0);
            }

            3./通信編程

            Linux本身只有進程的概念,而其所謂的線程本質(zhì)上在內(nèi)核里仍然是進程。大家知道,進程是資源分配的單位,同一進程中的多個線程共享該進程的資源(如作為共享內(nèi)存的全局變量)。Linux中所謂的線程只是在被創(chuàng)建的時候克隆(clone)了父進程的資源,因此,clone出來的進程表現(xiàn)為線程。Linux中最流行的線程機制為LinuxThreads,它實現(xiàn)了一種Posix1003.1cpthread標準接口。
            線程之間的通信涉及同步和互斥,互斥體的用法為:
            pthread_mutex_tmutex;
            pthread_mutex_init(mutex,NULL);//按缺省的屬性初始化互斥體變量mutex
            pthread_mutex_lock(mutex);//給互斥體變量加鎖
            …//臨界資源
            phtread_mutex_unlock(mutex);//給互斥體變量解鎖

            同步就是線程等待某個事件的發(fā)生。只有當(dāng)?shù)却氖录l(fā)生線程才繼續(xù)執(zhí)行,否則線程掛起并放棄處理器。當(dāng)多個線程協(xié)作時,相互作用的任務(wù)必須在一定的條件下同步。Linux下的C語言編程有多種線程同步機制,最典型的是條件變量(conditionvariable)。而在頭文件semaphore.h中定義的信號量則完成了互斥體和條件變量的封裝,按照多線程程序設(shè)計中訪問控制機制,控制對資源的同步訪問,提供程序設(shè)計人員更方便的調(diào)用接口。下面的生產(chǎn)者/消費者問題說明了Linux線程的控制和通信:
            #include
            #include
            #defineBUFFER_SIZE16
            structprodcons
            {
            intbuffer[BUFFER_SIZE];
            pthread_mutex_tlock;
            intreadpos,writepos;
            pthread_cond_tnotempty;
            pthread_cond_tnotfull;
            };
            /*初始化緩沖區(qū)結(jié)構(gòu)*/
            voidinit(structprodcons*b)
            {
            pthread_mutex_init(b->lock,NULL);
            pthread_cond_init(b->notempty,NULL);
            pthread_cond_init(b->notfull,NULL);
            b->readpos=0;
            b->writepos=0;
            }
            /*將產(chǎn)品放入緩沖區(qū),這里是存入一個整數(shù)*/
            voidput(structprodcons*b,intdata)
            {
            pthread_mutex_lock(b->lock);
            /*等待緩沖區(qū)未滿*/
            if((b->writepos+1)%BUFFER_SIZE==b->readpos)
            {
            pthread_cond_wait(b->notfull,b->lock);
            }
            /*寫數(shù)據(jù),并移動指針*/
            b->buffer[b->writepos]=data;

            b->writepos++;
            if(b->writepos>=BUFFER_SIZE)
            b->writepos=0;
            /*設(shè)置緩沖區(qū)非空的條件變量*/
            pthread_cond_signal(b->notempty);
            pthread_mutex_unlock(b->lock);
            }
            /*從緩沖區(qū)中取出整數(shù)*/
            intget(structprodcons*b)
            {
            intdata;
            pthread_mutex_lock(b->lock);
            /*等待緩沖區(qū)非空*/
            if(b->writepos==b->readpos)
            {
            pthread_cond_wait(b->notempty,b->lock);
            }
            /*讀數(shù)據(jù),移動讀指針*/
            data=b->buffer[b->readpos];
            b->readpos++;
            if(b->readpos>=BUFFER_SIZE)
            b->readpos=0;
            /*設(shè)置緩沖區(qū)未滿的條件變量*/
            pthread_cond_signal(b->notfull);
            pthread_mutex_unlock(b->lock);
            returndata;
            }
            /*測試:生產(chǎn)者線程將1到10000的整數(shù)送入緩沖區(qū),消費者線
            程從緩沖區(qū)中獲取整數(shù),兩者都打印信息*/
            #defineOVER(-1)
            structprodconsbuffer;
            void*producer(void*data)
            {
            intn;
            for(n=0;n10000;n++)
            {
            printf(%d--->n,n);
            put(buffer,n);
            }put(buffer,OVER);
            returnNULL;
            }
            void*consumer(void*data)
            {
            intd;
            while(1)
            {
            d=get(buffer);
            if(d==OVER)
            break;
            printf(--->%dn,d);
            }
            returnNULL;
            }
            intmain(void)
            {
            pthread_tth_a,th_b;
            void*retval;
            init(buffer);
            /*創(chuàng)建生產(chǎn)者和消費者線程*/
            pthread_create(th_a,NULL,producer,0);
            pthread_create(th_b,NULL,consumer,0);
            /*等待兩個線程結(jié)束*/
            pthread_join(th_a,retval);
            pthread_join(th_b,retval);
            return0;
            }

            4.小結(jié)

            本章主要給出了Linux平臺下文件、進程控制與通信、與通信的編程實例。至此,一個完整的,涉及硬件原理、Bootloader、操作系統(tǒng)及文件系統(tǒng)移植、驅(qū)動程序開發(fā)及應(yīng)用程序編寫的嵌入式Linux系列講解就全部結(jié)束了。

            本文引用地址:http://www.biyoush.com/article/257511.htm

            linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


            關(guān)鍵詞: 線程控制 進程 Linux

            評論


            相關(guān)推薦

            技術(shù)專區(qū)

            關(guān)閉