Unix/Linux操作系统下C的开发主要讲述Unix系统的原理和机制/提供的系统函数
概要
Unix/Linux的静态库和共享库
标C的错误处理(UC也适用)
Unix/Linux的内存管理
Unix/Linux的文件/目录操作
Unix/Linux的进程管理
Unix/Linux的信号机制
Unix的IPC(进程间通信)
网络编程
Unix/Linux的多线程编程
标准 行业的准则,所有的公司必须遵守; 产品 产品是以质量为主的软件,按照大多数用户的需求设计,而不是迎合某些特定客户的; 项目 针对特定的客户,受特定客户的控制;
Unix操作系统是美国AT&T公司于1971年在PDP-11上运行的操作系统;具有多用户多任务的特点,支持多种处理器架构,最早与1969年在AT&T的贝尔实验室开发; 贝尔实验室还研发了C语言;
Unix的三大派生版本
System V: AIX / Solaris / HP-UX / IRIX
Berkley: FreeBSD / NetBSD / OpenBSD / Mac OS X
Hybrid: Minix(Mini Unix迷你版类Unix) / Linux
- Linux是一种自由和开放源代码的类Unix系统; Tux(一只企鹅,全程为tuxedo)是Linux的标志;
- Linux和GNU结合做成了完整的操作系统,通过POSIX规范(标准)实现了和Unix系统的完美兼容,通过GNU通用许可协议GPL解决了版权的问题;
- GNU发起开始于1984年,由自由软件基金支持;GNU的基本原则是共享;
- GNU的主旨在于发展一个类Unix,并且为自由软件的完整操作系统,GNU系统;
- GNU提供shell和界面;
- POSIX是由IEEE和ISO/IEC开发的一簇标准;该标准是基于现有的Unix实践和经验,描述了操作系统的调用服务接口,用于保证编制的应用程序可以在源代码一级上在多个操作系统上移植运行;
- 非版权copyleft,带有标准的copyleft声明,确认作者的所有权和标志;它声明,任何人不但可以自由分发该成果,还可以自由地修改它,但你不能声明你做了原始的工作,或声明是由他人做的;最终,所有派生的成果必须遵循这一条款;
版本命名
旧计划(1.0到2.6版之间): A.B.C
新计划2.6.0(2003年10月之后): A.B.C.D
Linux特点
遵循GNU/GPL协议;
开放性;
多用户;
多任务;
设备独立性;
提供了丰富的网络功能;
可靠的系统安全;
良好的可移植性;
Linux常用发行版
大众的Ubuntu
锐意的Fedora
老牌的RedHat
优雅的LinuxMint
华丽的OpenSUSE
稳健的OpenEuler
自由的Debian
简洁的Slackware
本土化的Deepin
其中OpenEuler和Deepin为国内主导的发行版,OpenEuler主要应用于服务器边缘计算云计算与嵌入式,Deepin主要应用于个人及办公桌面系统。
GCC的选项和用法
-E 预处理,把预处理指令(以#开头的指令)处理掉
-S 生成汇编文件(.s文件)
-c 只编译不进行连接(不生成a.out)
-o 改变目标文件的名称
-O 可以优化
-g 生成调试信息
-v 查看gcc的版本
-Wall (Warning all)可以生成更多的警告信息,代码更规范;
-Werror 在所有产生警告的地方作为错误处理,停止编译;
-L 指定连接库目录
-l 指定连接库名
-I 指定头文件路径
计算机语言分为 机器语言,汇编语言和高级语言;
GCC编译过程可以细分为4个阶段
1. 预处理Pre-Processing;宏展开等,可以生成.i文件
gcc -E hello.c -o hello.i //带-o选项可以把输出到屏幕改为文件;
2. 编译Compiling(狭义的编译);进行语法分析,转换成汇编语言,生成.s文件
gcc -S hello.i //生成hello.s
3. 汇编Assembling;把汇编语言代码转换成目标代码,生成.o文件
gcc -c hello.s //生成hello.o
4. 连接Linking;连接器ld将as创建的目标文件转换为可执行文件,生成a.out文件
gcc hello.o
参考代码
/* hello.c */
#include <stdio.h>
int main() {
printf("Hello Unix C\n");
/* return 0; */
}
gcc hello.c -Wall -Werror 可以生成更多的警告信息;
与C语言相关的文件名后缀
.a //静态对象库
.c //需要预处理的C语言源代码
.h //C语言源代码头文件
.i //不需要预处理的C语言源代码
.o //目标文件
.s //汇编语言代码
.so //共享对象库
指定编译文件类型
-x指定编译代码类型:c/c++/assembler/none;
gcc -x c -Wall -0 main hello.c
如果是none,会根据扩展名自动确认;
关于头文件.h和源文件.c
各种声明一般都写在.h头文件中,各种实现都写在.c源文件中;
头文件的作用是给其他文件调用源文件时使用的;
C语言中,头文件一般放
- 变量的声明(赋值不行,赋值就属于定义要写在源文件中)
- 函数的声明(实现不行)
- 结构的声明
- 宏的定义
常见的预处理指令
#include <文件名>
#include "文件名"
将指定的文件插入到#include的位置; 尖括号先找系统;双引号先找当前位置,再找系统;
#define 宏 定义
定义宏变量或宏函数;
#undef 宏
删除宏;
#if/elif/else/endif/ifdef/ifndef/
条件编译;
#error 提示信息
产生错误,挂起预处理程序; 注:#error一旦产生错误,编译失败;
#warning 提示信息
创建一个警告;
#pragma
提供额外信息的标准方法,可以用来指定平台;增加额外功能;
#pragma GCC dependency 文件名a
比较当前文件和文件a的最后修改时间,如果当前文件是最近修改的就没问题,否则产生一个警告;
#pragma GCC poison 标识符
poison后面的标识符将被定为毒药,禁止继续使用,否则引发错误;
#pragma pack(整数)
pack(n)可以指定结构的对齐和补齐的字节数n;
#pragma pack(push,1)
#pragma pack(pop)
配合使用可以临时设置pack
#
转化为字符串,#define STR(x) #x
##
连接操作符号,用于宏内连接两个字符串;#define _CONCAT_(a, b) a##b
参考代码
/*
* 预处理指令演示
*/
#include <stdio.h> //C编译器比较宽松
#define VERSION 4
#if (VERSION < 3)
#error "版本过低" //停止编译
#elif (VERSION > 3)
#warning "版本较高" //可以不用双引号,此时中间不可有空格;
#endif
#pragma GCC dependency "01hello.c"
#pragma GCC poison goto
#pragma pack(2) //pack(1)是取消对齐和补齐
int main() {
//goto ok; //goto被限制使用
ok: printf("over\n"); //ok就是这个语句的标签
struct s {
char c1; //1
int i; //4
char c2; //1
};
printf("sizeof(struct) = %d\n", sizeof(struct s));
// pack(1)时结果为6
// pack(2)时结果为8
// pack(4)时结果为12
return 0;
}
#if宏与if语句的区别是: #if宏是有条件的编译,if语句是有条件的执行;