在Linux平台下的C程序开发的一般步骤1.安装所需的所有的软件。2.利用编辑器把程序的源代码编写到一个文件中。3.用C编译器gcc编译连接,生成可执行文件。4.用C调试器gdb调试程序。5.运行该可执行文件。•Linux下的C简介•文件的编辑•文件的编译—GCC•文件的调试---GDB•GNUmake内容Linux下的C编程/*Thisisexample1.c*/#includestdio.hintmain(intargc,char*argv[]){intarg;for(arg=0;argargc;arg++){if(argv[arg][0]==‘-’)printf(“Option:%s\n”,argv[arg]+1);elseprintf(“Argument%d:%s\n”,arg,argv[arg]);}exit(0);}example1能够把输入参数和参数的值分别显示出来,执行结果:$./example1–I–lr‘helloworld’–ffile.cArgument0:./example1Option:IOption:lrArgument3:helloworldOption:fArgument5:file.cLinux下的C编程•Linux系统C编程的特殊之处在于系统调用•系统调用是内核提供的、功能强大的一系列函数,它们在内核中实现,然后通过一定的方式呈现给用户,是用户程序和内核交互的接口。•使用原因:–为用户程序提供强大的系统支持–安全和效率系统调用文件操作/*Thisisexample2.c*/#includeunistd.h#includesys/stat.h#includefcntl.hintmain(){charc;intfd_src,fd_des;fd_src=open(“file.src”,O_RDONLY);fd_des=open(“file.des”,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);while(read(fd_src,&c,1)==1)write(fd_des,&c,1);exit(0);}•执行情况:$./example2$vifile.src12345678$vifile.des12345678•文件操作一个字节一个字节的复制,如果要提高复制速度呢charbuf[1024];while(nread=read(fd_src,buf,sizeof(buf))0)write(fd_des,buf,nread);exit(0);}内存管理/*Thisisexample3.c*/#includeunistd.h#includestdlib.h#includestdio.h#defineMEGABYTE(1024*1024)intmain(){char*some_memory;intmegabyte=MEGABYTE;intexit_code=EXIT_FAILURE;some_memory=(char*)malloc(megabyte);if(some_memory!=NULL){sprintf(some_memory,”helloworld\n”);printf(“%s”,some_memory);free(some_memory);exit_code=EXIT_SUCCESS;}exit(exit_code);}•执行情况:$./example3helloworld进程调度/*Thisisexample4.c*/#includeunistd.h#includesys/types.h#includestdio.hintmain(){pid_tpid;char*message;intn;printf(“forkprogramstarting\n”);pid=fork();进程调度switch(pid){case-1:exit(1);case0:message=“thisisthechild”;n=5;for(;n0;n--){sleep(1);puts(message);}break;default:message=“thisistheparent”;n=3;for(;n0;n--){sleep(1);puts(message);}break;}exit(0);}•执行情况:$./example4forkprogramstartingthisistheparentthisisthechildthisistheparentthisisthechildthisistheparent$thisisthechildthisisthechildthisisthechild进程调度/*Thisisexample5.c*/#includeunistd.h#includesys/types.h#includestdio.hintmain(){pid_tpid;char*message;intn;printf(“forkprogramstarting\n”);pid=vfork();进程调度switch(pid){case-1:exit(1);case0:message=“thisisthechild”;n=5;for(;n0;n--){sleep(1);puts(message);}break;default:message=“thisistheparent”;n=3;for(;n0;n--){sleep(1);puts(message);}break;}exit(0);}•执行情况:$./example5forkprogramstartingthisisthechildthisisthechildthisisthechildthisisthechildthisisthechildthisistheparentthisistheparentthisistheparent1.启动:vi[filename]2.退出::w保存;:wfilename另存为filename;:wq!保存退出;:wq!filename注:以filename为文件名保存后退出;:q!不保存退出;文件的编辑——Vi3.vi的两种命令模式;Command(命令)模式,用于输入命令;Insert(插入)模式,用于插入文本;插入模式(文本的插入);i在光标之前插入;a在光标之后插入;I在光标所在行的行首插入;A在光标所在行的行末插入;o在光标所在的行的上面插入一行;O在光标所在的行的下面插入一行;s删除光标后的一个字符,然后进入插入模式;S删除光标所在的行,然后进入插入模式;按ESC键返回Command(命令)模式文件的编辑——Vi例如建立一个最简单的例子---example6:启动Vi:Viexample6.c输入文本:#includestdio.hintmain(void)printf(GoodLucktoyou!\n);按ESC转化为命令模式。输入::wq退出。则example6.c建立。文件的编辑——Vi•编译过程预处理链接编译汇编源程序(*.c)可执行文件预处理器编译器汇编器连接器gcc命令的基本用法如下:gcc[options][filenames]GCC选项:-S只对文件进行编译,但不汇编和连接()-E只对文件进行预处理,但不编译汇编和连接-o[file1][file2]将文件file2编译成可执行文件file1-Idirectory为include文件的搜索指定目录-w禁止警告信息-Wall显示附加的警告信息-g显示排错信息以便用于gdb-m***根据不同的微处理器进行优化GCC编译器GCC编译过程通常按如下步骤进行:•首先,由C预处理程序CPP对文件进行分析。当分析文件时,处理条件编译,并执行宏替换等。•编译器对代码的语法进行分析。这时,将建立一个符号表并生成一种中间格式的文件。•汇编(AS),汇编编译生成的汇编代码,生成目标文件.•连接(ld),这一步将把不同的文件和库连接起来。GCC编译器•编译生成的Linux系统中的可执行文件有两种格式:•第一种格式是a.out格式,这种格式用于早期的Linux系统以及Unix系统的原始格式。•另外一种为可执行可连接的格式(ELF)。•ELF格式已经被Linux系统作为标准的格式采用。gcc编译程序产生的所有的二进制文件都是ELF格式的文件(即使可执行文件的默认名仍然是a.out)。例:在gcc中用开关-Wall对刚刚建立的example6.c进行编译:$gcc–Wall-oexample6example6.c将得到如下信息:example6.c:4:warning:controlreachesendofnon-voidfunction原因:main()函数被声明为返回一个整型,但实际上是没有被定义的。程序可以改正如下:GCC编译器#include〈Stdio.h〉intmain(void){print(”GoodLucktoyou!\n);return0;}执行程序:$./example6得到如下结果:GoodLucktoyou!习题:计算一个数的阶乘习题•编辑文件$Vifactorial.c输入以下源代码#includestdio.h#includestdlib.hintfactorial(intn);intmain(intargc,char**argv){intn;if(argc2){printf(Usage:%sn\n,argv[0]);return-1;}else{n=atoi(argv[1]);printf(Factorialof%dis%d.\n,n,factorial(n));}return0;}intfactorial(intn){if(n=1)return1;elsereturnfactorial(n-1)*n;}存盘退出编译:$gcc-ofactorialmain.cfactorial.c执行:$./factorial5执行结果:Factorialof5is120.GCC优化选项•有很多选项可用于告诉gcc,在耗费更多编译时间和牺牲易调试性的基础上,产生更小更快的可执行文件。这些选项中最典型的是-O和-O2选项。•-O选项告诉gcc对源代码进行基本优化。这些优化在大多数情况下都会使程序执行的更快。•-O2选项告诉gcc产生尽可能小和尽可能快的代码。-O2选项将使编译的速度比使用-O时慢。但通常产生的代码执行速度会更快。它是一个符号调试程序。当程序编译时利用-g参数,符号表将被保留,此时可以利用符号调试程序来追踪程序的错误。基本的方法是,在信息转储后利用gdb从而获取堆栈的跟踪信息,从获取的信息中,可以找到信息转储发生所在的源行,以及在那一行被调用的函数。调试工具GDBgdb功能:♦监视程序中变量的值的变化;♦设置断点,使程序在指定的代码行上暂停执行,便于观察;♦单步执行代码;♦分析崩溃程序产生的core文件。命令形式:启动:gdbfilename退出gdb:(gdb)quit调试工具GDBgdb常用命令:♦file装入想要调试的可执行文件.♦kill终止正在调试的程序.♦list列出产生执行文件的源代码的一部分.♦next执行一行源代码但不进入函数内部.♦step执行一行源代码而且进入函数内部.♦run执行当前被调试的程序♦quit终止gdb♦watch使你能监视一个变量的值而不管它何时被改变.♦break在代码里设置断点,这将使程序执行到这里时被挂起.♦make使你能不退出gdb就可以重新产生可执行文件.♦shell使你能不离开gdb就执行UNIXshell命令.♦print或display:显示表达式的值.♦set命令:显示数据并能够修改变量的值调试工具GDB•开发大中型系统时,系统总是划分成多个模块,各个模块之间相互以来的关系错综复杂,当部分改变文件时,重新编译非常麻烦,在Linux中提供一个自动生成和维护程序的工具——make,其特点是: