溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux常用的C語言開發(fā)工具是什么

發(fā)布時間:2022-01-26 16:14:24 來源:億速云 閱讀:174 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Linux常用的C語言開發(fā)工具是什么”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Linux常用的C語言開發(fā)工具是什么”文章能幫助大家解決問題。

Linux常用的C語言開發(fā)工具是什么

linux下的C語言開發(fā)(makefile編寫) 對于程序設(shè)計員來說,makefile是我們繞不過去的一個坎。可能對于習(xí)慣Visual C++的用戶來說,是否會編寫makefile無所謂。畢竟工具本身已經(jīng)幫我們做好了全部的編譯流程。但是在Linux上面,一切變得不一樣了,沒有人會為你做這一切。編代碼要靠你,測試要靠你,最后自動化編譯設(shè)計也要靠你自己。想想看,如果你下載了一個開源軟件,卻因為自動化編譯失敗,那將會在很大程度上打擊你學(xué)習(xí)代碼的自信心了。所以,我的理解是這樣的。我們要學(xué)會編寫makefile,至少會編寫最簡單的makefile。

首先編寫add.c文件,

     #include "test.h"
 
     #include 
     int add(int a, int b)
 
     {
 
         return a + b;
 
     }
 
     int main()
 
     {
 
         printf(" 2 + 3 = %d\n", add(2, 3));
 
         printf(" 2 - 3 = %d\n", sub(2, 3));
 
         return 1;
 
     }

再編寫sub.c文件,

     #include "test.h"
 
     int sub(int a, int b)
 
     {
 
         return a - b;
 
     }

最后編寫test.h文件,

     #ifndef _TEST_H
 
     #define _TEST_H
 
     int add(int a, int b);
 
     int sub(int a, int b);
 
     #endif

那么,就是這三個簡單的文件,應(yīng)該怎么編寫makefile呢?

     test:
 
     add.o sub.o
 
     gcc -o test add.o sub.o
 
     add.o:
 
     add.c test.h
 
     gcc -c add.c
 
     sub.o:
 
     sub.c test.h
 
     gcc -c sub.c
 
     clean:
 
     rm -rf test
 
     rm -rf *.o

linux下的C語言開發(fā)(gdb調(diào)試) 編寫代碼過程中少不了調(diào)試。在windows下面,我們有visual studio工具。在linux下面呢,實際上除了gdb工具之外,你沒有別的選擇。那么,怎么用gdb進行調(diào)試呢?我們可以一步一步來試試看。

 #include  int iterate(int value)   {     if(1 == value)       return 1;     return iterate(value – 1) + value;   }   int main()   {     printf(“%d\n”, iterate(10));     return 1;   }

既然需要調(diào)試,那么生成的可執(zhí)行文件就需要包含調(diào)試的信息,這里應(yīng)該怎么做呢?很簡單,輸入 gcc test.c -g -o test。輸入命令之后,如果沒有編譯和鏈接方面的錯誤,你就可以看到 可執(zhí)行文件test了。

調(diào)試的步驟基本如下所示, (01) 首先,輸入gdb test (02) 進入到gdb的調(diào)試界面之后,輸入list,即可看到test.c源文件 (03) 設(shè)置斷點,輸入 b main (04) 啟動test程序,輸入run (05) 程序在main開始的地方設(shè)置了斷點,所以程序在printf處斷住 (06) 這時候,可以單步跟蹤。s單步可以進入到函數(shù),而n單步則越過函數(shù) (07) 如果希望從斷點處繼續(xù)運行程序,輸入c (08) 希望程序運行到函數(shù)結(jié)束,輸入finish (09) 查看斷點信息,輸入 info break (10) 如果希望查看堆棧信息,輸入bt (11) 希望查看內(nèi)存,輸入 x/64xh + 內(nèi)存地址 (12) 刪除斷點,則輸入delete break + 斷點序號 (13) 希望查看函數(shù)局部變量的數(shù)值,可以輸入print + 變量名 (14)希望修改內(nèi)存值,直接輸入 print + *地址 = 數(shù)值 (15) 希望實時打印變量的數(shù)值,可以輸入display + 變量名 (16) 查看函數(shù)的匯編代碼,輸入 disassemble + 函數(shù)名 (17) 退出調(diào)試輸入quit即可

linux下的C語言開發(fā)(AT&T 匯編語言) 同樣是x86的cpu,但是卻可以用不同形式的匯編語言來表示。 在window上面我們使用的更多是intel格式的匯編語言,而在Linux系統(tǒng)上面使用的更多的常常是AT&T格式的匯編語言。那什么是AT&T格式的匯編代碼呢?我們可以寫一個試試看。

     .data
 
     message: .string "hello!\n"
 
     length = . - message
 
     .text
 
     .global _start
 
     _start:
 
     movl $length, %edx
 
     movl $message, %ecx
 
     movl $1, %ebx
 
     movl $4, %eax
 
     int $0x80
 
     movl $0, %ebx
 
     movl $1, %eax
 
     int $0x80
     08048074 :
 
     .text
 
     .global _start
 
     _start:
 
     movl $length, %edx
 
     8048074: ba 08 00 00 00 mov $0x8,%edx
 
     movl $message, %ecx
 
     8048079: b9 9c 90 04 08 mov $0x804909c,%ecx
 
     movl $1, %ebx
 
     804807e: bb 01 00 00 00 mov $0x1,%ebx
 
     movl $4, %eax
 
     8048083: b8 04 00 00 00 mov $0x4,%eax
 
     int $0x80
 
     8048088: cd 80 int $0x80
 
     movl $0, %ebx
 
     804808a: bb 00 00 00 00 mov $0x0,%ebx
 
     movl $1, %eax
 
     804808f: b8 01 00 00 00 mov $0x1,%eax
 
     int $0x80
 
     8048094: cd 80 int $0x80
 
     ret
 
     8048096: c3 ret

 這是一個簡單的匯編文件,我們可以分兩步進行編譯。首先,輸入 as -gstabs -o hello.o hello.s, 接著輸入ld -o hello hello.o即可。為了驗證執(zhí)行文件是否正確,可以輸入./hello驗證一下。 在as命令當(dāng)中,由于我們使用了-gstabs選項,因此在hello執(zhí)行文件中是包含調(diào)試信息的。所以,如果想單步調(diào)試的朋友可以輸入gdb hello進行調(diào)試。 那么,hello執(zhí)行文件反匯編的代碼又是什么樣的呢?我們可以輸入objdump -S -d hello查看一下。

linux下的C語言開發(fā)(靜態(tài)庫) 在我們編寫軟件的過程當(dāng)中,少不了需要使用別人的庫函數(shù)。因為大家知道,軟件是一個協(xié)作的工程。作為個人來講,你不可能一個人完成所有的工作。另外,網(wǎng)絡(luò)上一些優(yōu)秀的開源庫已經(jīng)被業(yè)內(nèi)廣泛接受,我們也沒有必要把時間浪費在這些重復(fù)的工作上面。 既然說到了庫函數(shù),那么一般來說庫函數(shù)分為兩種方式:靜態(tài)庫和動態(tài)庫。兩者的區(qū)別其實很小,靜態(tài)庫是必須要鏈接到執(zhí)行文件中去的,而動態(tài)庫是不需要鏈接到最后的執(zhí)行文件中的。怎么理解呢?也就是說,對于最后的執(zhí)行文件而言,你是否刪除靜態(tài)庫無所謂。但是,一旦你刪除了動態(tài)庫,最后的執(zhí)行文件就玩不轉(zhuǎn)了。 今天我們討論的問題是靜態(tài)庫。為了顯示windows和linux創(chuàng)建靜態(tài)庫之間的差別,我們首先在windows上面利用Visual C++6.0創(chuàng)建一個靜態(tài)庫。源文件的代碼很簡單,

     #include "test.h"
 
     int add(int a, int b)
 
     {
 
         return a + b;
 
     }

頭文件代碼也不難,

     #ifndef _TEST_H
 
     #define _TEST_H
 
     int add(int a, int b);
 
     #endif

如果你需要在windows上面創(chuàng)建一個靜態(tài)庫,那么你需要進行下面的操作, (1)打開visual C++ 6.0工具,單擊【File】-> 【New】->【Projects】 (2)選擇【W(wǎng)in32 Static Library】,同時在【Project Name】寫上項目名稱,在【Location】選擇項目保存地址 (3)單擊【Ok】,繼續(xù)單擊【Finish】,再單擊【Ok】,這樣一個靜態(tài)庫工程就創(chuàng)建好了 (4)重新單擊【File】->【New】->【Files】,選擇【C++ Source Files】, (5)選中【Add to pproject】,將源文件加入到剛才創(chuàng)建的工程中去,在File中輸入文件名+.c后綴 (6)重復(fù)4、5的操作,加入一個文件名+.h頭文件 (7)分別在頭文件和源文件中輸入上面的代碼,單擊F7按鈕,即可在Debug目錄中生成*.lib靜態(tài)庫文件

那么,在linux下面應(yīng)該怎么運行呢?其實很簡單,兩條命令解決, (1)首先生成*.o文件,輸入gcc -c test.c -o test.o (2)利用ar命令生成靜態(tài)庫,輸入ar rc libtest.a test.o

此時如果還有一個hello.c文件使用到了這個靜態(tài)庫,比如說 ,

     #include 
     #include "test.h"
 
     int main()
 
     {
 
         printf("%d\n", add(2, 3));
 
         return 1;
 
     }

其實也很簡單,輸入一個簡單的命令就可以生成執(zhí)行文件了, (1)首先輸入gcc hello.c -o hello ./libtest.a (2)輸入./hello,驗證生成的執(zhí)行文件是否正確 (3)朋友們可以刪除libtest.a文件,重新輸入./hello,驗證執(zhí)行文件是否可以正常運行

linux下的C語言開發(fā)(動態(tài)庫) 動態(tài)鏈接庫不是linux獨有的特性,在windows下面也存在這樣的特性。一般來說,windows下面的動態(tài)連接庫是以.dll作為結(jié)尾的,而linux下面的動態(tài)連接庫是以.so結(jié)尾的。和靜態(tài)鏈接庫相比,動態(tài)連接庫可以共享內(nèi)存資源,這樣可以減少內(nèi)存消耗。另外,動態(tài)連接是需要經(jīng)過操作系統(tǒng)加載器的幫助才能被普通執(zhí)行文件發(fā)現(xiàn)的,所以動態(tài)連接庫可以減少鏈接的次數(shù)。有了這個特點,我們就不難發(fā)現(xiàn)為什么很多軟件的補丁其實都是以動態(tài)庫發(fā)布的。

那么,在Linux上動態(tài)庫是怎么生成的呢?

     #include "test.h"
 
     int add(int a, int b)
 
     {
 
         return a + b;
 
     }

頭文件格式,

     #ifndef _TEST_H
 
     #define _TEST_H
 
     int add(int a, int b);
 
     #endif

此時如果我們想要生成動態(tài)庫,要做的工作其實非常簡單,輸入gcc -shared -fPIC -o libtest.so test.c即可。回車后輸入ls,我們就可以發(fā)現(xiàn)當(dāng)前目錄下面出現(xiàn)了libtest.so文件。

     #include 
     #include "test.h"
 
     int main()
 
     {
 
         printf("%d\n", add(2, 3));
 
         return 1;
 
     }

在上面的代碼當(dāng)中,我們發(fā)現(xiàn)使用到了add函數(shù),那么此時如何才能生成一個執(zhí)行文件呢?也很簡單,輸入gcc hello.c -o hello ./libtest.so。然后輸入./hello,此時可以驗證一下執(zhí)行文件運行是否正確。在編寫靜態(tài)庫的時候,我說過靜態(tài)庫是匯編鏈接到執(zhí)行文件當(dāng)中的,而動態(tài)庫不會。朋友們可以做個小實驗,刪除libtest.so,然后輸入./hello。此時大家可以看看系統(tǒng)有沒有錯誤返回? 這個時候,有的朋友就會問了,那在windows下面dll應(yīng)該怎么編寫呢?其實也不難,只要在test.h上面稍作改變即可。其他的步驟和靜態(tài)庫的操作是基本類似的。

     #ifndef _TEST_H
 
     #define _TEST_H
 
     #ifdef USR_DLL
 
     #define DLL_API _declspec(dllexport)
 
     #else
 
     #define DLL_API _declspec(dllimport)
 
     #endif
 
     DLL_API int add(int a, int b);
 
     #endif

linux下的C語言開發(fā)(定時器) 定時器是我們需要經(jīng)常處理的一種資源。那linux下面的定時器又是怎么一回事呢?其實,在linux里面有一種進程中信息傳遞的方法,那就是信號。這里的定時器就相當(dāng)于系統(tǒng)每隔一段時間給進程發(fā)一個定時信號,我們所要做的就是定義一個信號處理函數(shù)。

     #include 
     #include 
     #include 
     #include 
     #include 
     static int count = 0;
 
     static struct itimerval oldtv;
 
     void set_timer()
 
     {
 
         struct itimerval itv;
 
         itv.it_interval.tv_sec = 1;
 
         itv.it_interval.tv_usec = 0;
 
         itv.it_value.tv_sec = 1;
 
         itv.it_value.tv_usec = 0;
 
         setitimer(ITIMER_REAL, &itv, &oldtv);
 
     }
 
     void signal_handler(int m)
 
     {
 
         count ++;
 
         printf("%d\n", count);
 
     }
 
     int main()
 
     {
 
         signal(SIGALRM, signal_handler);
 
         set_timer();
 
         while(count linux下的C語言開發(fā)(自動編譯工具) 在Linux下面,編寫makefile是一件辛苦的事情。因此,為了減輕程序員編寫makefile的負(fù)擔(dān),人們發(fā)明了autoconf和automake這兩個工具,可以很好地幫我們解決這個問題。 我們可以通過一個簡單的示例來說明如何使用配置工具。(1)首先,編寫源文件hello.c。     #include 
     int main(int argc, char** argv[])
 
     {
 
         printf("hello, world!\n");
 
         return 1;
 
     }(2)接下來,我們需要創(chuàng)建一個Makefile.am,同時編寫上腳本。     SUBDIRS=
 
     bin_PROGRAMS=hello
 
     hello_SOURCES=hello.c(3)直接輸入autoscan,生成文件configure.scan,再改名為configure.in。修改腳本AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)為AC_INIT(hello, 1.0, feixiaoxing@163.com)同時,在AC_CONFIG_HEADER([config.h])后面添加AM_INIT_AUTOMAKE(hello, 0.1) (4)依次輸入aclocal命令、autoheader命令 (5)創(chuàng)建4個文件,分別為README、NEWS、AUTHORS和ChangeLog (6)依次輸入automake -a、autoconf命令 (7)輸入./configure,生成最終的Makefile (8)如果需要編譯,輸入make;如果需要安裝, 輸入make install;如果需要發(fā)布軟件包,輸入make distlinux下的C語言開發(fā)(進程創(chuàng)建) 在Linux下面,創(chuàng)建進程是一件十分有意思的事情。我們都知道,進程是操作系統(tǒng)下面享有資源的基本單位。那么,在Linux下面應(yīng)該怎么創(chuàng)建進程呢?其實非常簡單,一個fork函數(shù)就可以搞定了。但是,我們需要清楚的是子進程與父進程之間除了代碼是共享的之外,堆棧數(shù)據(jù)和全局?jǐn)?shù)據(jù)均是獨立的。     #include 
     #include 
     #include 
     #include 
     #include 
     #include 
     #include 
     int main()
 
     {
 
         pid_t pid;
 
         if(-1 == (pid = fork())) {
 
             printf("Error happened in fork function!\n");
 
             return 0;
 
         }
 
         if(0 == pid) {
 
             printf("This is child process: %d\n", getpid());
 
         } else {
 
             printf("This is parent process: %d\n", getpid());
 
         }
 
         return 0;
 
     }linux下的C語言開發(fā)(進程等待) 所謂進程等待,其實很簡單。前面我們說過可以用fork創(chuàng)建子進程,那么這里我們就可以使用wait函數(shù)讓父進程等待子進程運行結(jié)束后才開始運行。注意,為了證明父進程確實是等待子進程運行結(jié)束后才繼續(xù)運行的,我們使用了sleep函數(shù)。但是,在linux下面,sleep函數(shù)的參數(shù)是秒,而windows下面sleep的函數(shù)參數(shù)是毫秒。     #include 
     #include 
     #include 
     int main(int argc, char* argv[])
 
     {
 
         pid_t pid;
 
         pid = fork();
 
         if(0 == pid) {
 
             printf("This is child process, %d\n", getpid());
 
             sleep(5);
 
         } else {
 
             wait(NULL);
 
             printf("This is parent process, %d\n", getpid());
 
         }
 
         return 1;
 
     }下面,我們需要做的就是兩步,首先輸入gcc fork.c -o fork, 然后輸入./fork,就會在console下面獲得這樣的結(jié)果。     [root@localhost fork]# ./fork
 
     This is child process, 2135
 
     This is parent process, 2134linux下的C語言開發(fā)(信號處理) 信號處理是linux程序的一個特色。用信號處理來模擬操作系統(tǒng)的中斷功能,對于我們這些系統(tǒng)程序員來說是最好的一個選擇了。要想使用信號處理功能,你要做的就是填寫一個信號處理函數(shù)即可。一旦進程有待處理的信號處理,那么進程就會立即進行處理。     #include 
     #include 
     #include 
     int value = 0;
 
     void func(int sig)
 
     {
 
         printf("I get a signal!\n");
 
         value = 1;
 
     }
 
     int main()
 
     {
 
         signal(SIGINT, func);
 
         while(0 == value)
 
             sleep(1);
 
         return 0;
 
     }為了顯示linux對signal的處理流程,我們需要進行兩個步驟。 第一,輸入gcc sig.c -o sig, 然后輸入./sig即可; 第二則重啟一個console窗口,輸入ps -aux | grep sig, 在獲取sig的pid之后然后輸入kill -INT 2082, 我們即可得到如下的輸出。     [root@localhost fork]#./sig
 
     I get a signal!
 
     [root@localhost fork]#linux下的C語言開發(fā)(管道通信) Linux系統(tǒng)本身為進程間通信提供了很多的方式,比如說管道、共享內(nèi)存、socket通信等。管道的使用十分簡單,在創(chuàng)建了匿名管道之后,我們只需要從一個管道發(fā)送數(shù)據(jù),再從另外一個管道接受數(shù)據(jù)即可。     #include 
     #include 
     #include 
     #include 
     int pipe_default[2];
 
     int main()
 
     {
 
         pid_t pid;
 
         char buffer[32];
 
         memset(buffer, 0, 32);
 
         if(pipe(pipe_default)  0) {
 
                 printf("Receive data from server, %s!\n", buffer);
 
             }
 
             close(pipe_default[0]);
 
         } else {
 
             close(pipe_default[0]);
 
             if(-1 != write(pipe_default[1], "hello", strlen("hello"))) {
 
                 printf("Send data to client, hello!\n");
 
             }
 
             close(pipe_default[1]);
 
             waitpid(pid, NULL, 0);
 
         }
 
         return 1;
 
     }下面我們就可以開始編譯運行了,老規(guī)矩分成兩步驟進行: (1)輸入gcc pipe.c -o pipe; (2)然后輸入./pipe,過一會兒你就可以看到下面的打印了。     [test@localhost pipe]$ ./pipe
 
     Send data to client, hello!
 
     Receive data from server, hello!linux下的C語言開發(fā)(多線程編程) 多線程和多進程還是有很多區(qū)別的。其中之一就是,多進程是linux內(nèi)核本身所支持的,而多線程則需要相應(yīng)的動態(tài)庫進行支持。對于進程而言,數(shù)據(jù)之間都是相互隔離的,而多線程則不同,不同的線程除了堆??臻g之外所有的數(shù)據(jù)都是共享的。說了這么多,我們還是自己編寫一個多線程程序看看結(jié)果究竟是怎么樣的。     #include 
     #include 
     #include 
     #include 
     void func_1(void* args)
 
     {
 
         while(1) {
 
             sleep(1);
 
             printf("this is func_1!\n");
 
         }
 
     }
 
     void func_2(void* args)
 
     {
 
         while(1) {
 
             sleep(2);
 
             printf("this is func_2!\n");
 
         }
 
     }
 
     int main()
 
     {
 
         pthread_t pid1, pid2;
 
         if(pthread_create(&pid1, NULL, func_1, NULL)) {
 
             return -1;
 
         }
 
         if(pthread_create(&pid2, NULL, func_2, NULL)) {
 
             return -1;
 
         }
 
         while(1) {
 
             sleep(3);
 
         }
 
         return 0;
 
     }和我們以前編寫的程序有所不同,多線程代碼需要這樣編譯,輸入gcc thread.c -o thread -lpthread,編譯之后你就可以看到thread可執(zhí)行文件,輸入./thread即可。     [test@localhost Desktop]$ ./thread
 
     this is func_1!
 
     this is func_2!
 
     this is func_1!
 
     this is func_1!
 
     this is func_2!
 
     this is func_1!
 
     this is func_1!
 
     this is func_2!
 
     this is func_1!
 
     this is func_1!linux下的C語言開發(fā)(線程等待) 和多進程一樣,多線程也有自己的等待函數(shù)。這個等待函數(shù)就是pthread_join函數(shù)。那么這個函數(shù)有什么用呢?我們其實可以用它來等待線程運行結(jié)束。     #include 
     #include 
     #include 
     #include 
     void func(void* args)
 
     {
 
         sleep(2);
 
         printf("this is func!\n");
 
     }
 
     int main()
 
     {
 
         pthread_t pid;
 
         if(pthread_create(&pid, NULL, func, NULL)) {
 
             return -1;
 
         }
 
         pthread_join(pid, NULL);
 
         printf("this is end of main!\n");
 
         return 0;
 
     }編寫wait.c文件結(jié)束之后,我們就可以開始編譯了。首先你需要輸入gcc wait.c -o wait -lpthread,編譯之后你就可以看到wait可執(zhí)行文件,輸入./wait即可。     [test@localhost thread]$ ./thread
 
     this is func!
 
     this is end of main!linux下的C語言開發(fā)(線程互斥) 對于編寫多線程的朋友來說,線程互斥是少不了的。在linux下面,編寫多線程常用的工具其實是pthread_mutex_t。本質(zhì)上來說,它和Windows下面的mutex其實是一樣的,差別幾乎是沒有。希望對線程互斥進行詳細(xì)了解的朋友可以看這里。     #include 
     #include 
     #include 
     #include 
     static int value = 0;
 
     pthread_mutex_t mutex;
 
     void func(void* args)
 
     {
 
         while(1) {
 
             pthread_mutex_lock(&mutex);
 
             sleep(1);
 
             value ++;
 
             printf("value = %d!\n", value);
 
             pthread_mutex_unlock(&mutex);
 
         }
 
     }
 
     int main()
 
     {
 
         pthread_t pid1, pid2;
 
         pthread_mutex_init(&mutex, NULL);
 
         if(pthread_create(&pid1, NULL, func, NULL)) {
 
             return -1;
 
         }
 
         if(pthread_create(&pid2, NULL, func, NULL)) {
 
             return -1;
 
         }
 
         while(1)
 
             sleep(0);
 
         return 0;
 
     }編寫mutex.c文件結(jié)束之后,我們就可以開始編譯了。首先你需要輸入gcc mutex.c -o mutex -lpthread,編譯之后你就可以看到mutex可執(zhí)行文件,輸入./mutex即可。     [test@localhost thread]$ ./mutex
 
     value = 1!
 
     value = 2!
 
     value = 3!
 
     value = 4!
 
     value = 5!
 
     value = 6!

關(guān)于“Linux常用的C語言開發(fā)工具是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI