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...
相关推荐
Rousson3 分钟前
硬件学习笔记--82 连接器的选用原则与流程
笔记·单片机·学习
Larry_Yanan2 小时前
QML学习笔记(四十)QML的ApplicationWindow和StackView
c++·笔记·qt·学习·ui
YouEmbedded2 小时前
解码Linux文件IO目录检索与文件属性
linux·文件属性·文件io·目录检索
开开心心loky4 小时前
[iOS] KVC 学习
学习·ios·objective-c·cocoa
哲Zheᗜe༘5 小时前
了解学习Python编程之python基础
开发语言·python·学习
大聪明-PLUS5 小时前
关于新的 Linux 内核接口 gpio uapi 的说明
linux·嵌入式·arm·smarc
youliroam5 小时前
成语接龙学习
学习·golang·uniapp·成语接龙
玉树临风江流儿5 小时前
Linux驱动开发总结速记
linux·运维·驱动开发
cccyi76 小时前
Linux 进程信号机制详解
linux·signal·volatile
gd63213747 小时前
银河麒麟 aarch64 linux 里面的 qt 怎么安装kit
linux·服务器·qt