Linux系统编程学习笔记

1 前言

1.1 环境

平台:uabntu20.04

工具:vim,gcc,make

1.2 GCC

Linux系统下的GCC(GNU Compiler Collection)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。

GCC编译器能将C、C++语言源程序、汇程式化序和目标程序编译、链接成可执行文件,如果没有给出可执行文件的名字,gcc将生成一个名为a.out的文件。

GCC编译器编译C源文件为可执行文件的步骤:

C源文件---->预处理.i---->编译.s(生成汇编文件)---->汇编.o/.obj(生成目标文件)---->链接.out(生成可执行文件)---->可执行文件

gcc命令参数(选项)

参数 含义 示例

|----|----------------------------------------|------------------------------------------------------|
| 参数 | 含义 | 示例 |
| -c | 对文件进行预处理、编译和汇编,生成obj文件 | gcc -c hello.c |
| -S | 只进行预处理和编译,生成汇编代码 | gcc -S hello.c |
| -E | 只进行预处理,这个选项不生成文件,可以使用重定向或者-o选项使其生成一个文件 | gcc -E hello.c > hello.i或者gcc -E hello.c -o hello.i |
| -o | 指定目标的名称,默认为a.out | gcc -o hello hello.c |

过程演示

例如源代码main.c:

cs 复制代码
#include<stdio.h>

int main(void) {
    printf("Hello World!\n");
    return 0; 
}

预编译:这个过程处理宏定义和include,去除注释,不会对语法进行检查。可以看到预编译后,源文件的代码从6行扩展了很多行,生成main.i

cs 复制代码
gcc -E main.c > main.i # 或者 gcc -E main.c -o main.i
cs 复制代码
// ...
// 只展示了一部分
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;


extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 943 "/usr/include/stdio.h" 3 4

# 2 "main.c" 2
int main(void) {
    printf("Hello World!\n");
    return 0;
}

编译:这个阶段,检查语法,生成汇编代码main.s

cs 复制代码
gcc -S main.c -o main.s
cs 复制代码
        .file   "main.c"
        .section        .rodata
.LC0:
        .string "Hello World!"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $.LC0, %edi
        call    puts
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
        .section        .note.GNU-stack,"",@progbits

汇编:这个阶段,生成目标代码main.o

cs 复制代码
gcc -c main.s -o main.o

链接:生成可执行代码main。

链接分为两种,一种是静态链接,另外一种是动态链接。

使用静态链接的好处是,依赖的动态链接库较少,对动态链接库的版本不会很敏感,具有较好的兼容性;缺点是生成的程序比较大。

使用动态链接的好处是,生成的程序比较小,占用较少的内存。

cs 复制代码
gcc main.o -o main

运行

cs 复制代码
[root@HongyiZeng c]# ./main
Hello World!

1.3 make

make命令是GNU工程化中的一个编译工具。make是依赖于Makefile来编译多个源文件的工具。在Makefile里同样是用gcc(或者别的编译器)来编译程序。

可以使用以下命令直接生成可执行文件:

cs 复制代码
make main

直接运行

cs 复制代码
[root@HongyiZeng c]# ./main
Hello World!

1.4 makefile

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。

1.4.1 使用gcc的例子

创建文件:

cs 复制代码
touch main.c tool1.c tool1.h tool2.c tool2.h

可以使用vim * -p打开当前目录下的所有文件。-p是打开多个文件的选项。

在命令模式下,gt切换到下一个标签页,gT切换到上一个标签页。

退出多个标签时,可加上a,例如:qa或者:wqa等

tool1.h和tool1.c

cs 复制代码
#ifndef __TOOL1_H__
#define __TOOL1_H__
    void mytool1();
#endif
cs 复制代码
#include <stdio.h>
#include "tool1.h" 
void mytool1() {
	printf("tool1 print...\n");
}

tool2.h和tool2.c

cs 复制代码
#ifndef __TOOL2_H__
#define __TOOL2_H__
    void mytool2();
#endif
cs 复制代码
#include <stdio.h>
#include "tool2.h"

void mytool2() {
    printf("tool2 print...\n");
}

main.c

cs 复制代码
#include "tool1.h"
#include "tool2.h"

int main(void) {
    mytool1();
    mytool2();
    return 0;
}

对所有文件进行编译:

cs 复制代码
gcc *.c

执行a.out

cs 复制代码
[root@HongyiZeng makefile]# ./a.out 
tool1 print...
tool2 print...
相关推荐
学长毕设18 小时前
基于SpringBoot的青少年编程学习平台系统-附源码
spring boot·学习·青少年编程
readhere18 小时前
从ZYNQ7000开发板,学会启动嵌入式Linux系统——入门学习:EBAZ4205篇目录
linux·启动·嵌入式linux·zynq7000·ebaz4205
打工仔折腾 AI19 小时前
在 Ubuntu ARM64 部署 Q1 V3.0 MuJoCo 模型:加载、单步推理与执行器响应解析
linux·运维·人工智能·python·深度学习·ubuntu·性能优化
‎ദ്ദിᵔ.˛.ᵔ₎19 小时前
关于Linux 线程局部存储的认识
linux·运维
小小de风呀21 小时前
de风——【从零开始学习Linux】(九):进程基础 —— 从冯诺依曼体系到 fork 创建进程
linux·学习
李某学编程21 小时前
基于ARM的微机原理学习笔记(一)
arm开发·笔记·学习
Song_RsHt1 天前
Redis 与微服务,什么场景下无可替代
java·redis·后端·学习·微服务
sbjdhjd1 天前
AI产业周度动态:从“更强模型”走向“可执行、可治理、可计价”的系统竞争 (2026年10月19日—10月25日)
人工智能·笔记·ai·开源·gemini·信息差·claude code
晚风吹北巷1 天前
Linux复习篇(自用)
linux·运维·服务器·1024程序员节