在linux环境下的C语言编程,超全面概括

静态库
1.生成目标文件 gcc -c x.c —> x.o
2.把目标文件ar成静态库 ar -r libxxx.a x.p …
3.使用静态库:
gcc .c -I 头文件路径 -lxxx -L 静态库路径
CPATH C_INCLUDE_PATH LIBRARY_PATH

动态库
1.生成目标文件 gcc .c -fpic x.c —> x.o
2.编译成动态库 gcc -shared x.o … libxxx.so
3.使用动态库
gcc .c -I 头文件路径 -lxxx -L 动态库路径
CPATH LIBRARY_PATH
动态程序: LD_LIBRARY_PATH

静态库和动态库的区别:
1.静态库比较小,如果使用静态库的程序执行效率比较高,可执行文件比较大
在编译时会把静态库的寒素代码拷贝到可执行文件中,可执行程序在执行过程中不 依赖静态库
2.动态库比较大,如哦使用动态库的程序执行效率稍低,可执行文件比较小
在编译时,如果调用了动态库中的函数会生成调用指令,等到执行时,再跳到动态库指定位置执行

不管是动态库还是静态库都需要提供头文件

错误处理
#include<errno.h>
errno 错误码 当系统调用出错时会设置errno 程序调用成功时不会置0
通过errno获取错误信息:
1.perror()
2.strerror(errno)
3.%m
环境列表
char **environ;
环境列表是一个字符指针数组,以NULL为结束标识
数组中的每一项,都保存着一个环境配置项的地址
char *getenv(const char *name)
int setenv(const char *name,const char *val,int overwrite)
int putenv(const char *string)
void clearenv()
int unsetenv(const char *name)

进程映像
1.程序是保存在磁盘上的可执行文件
2.运行程序时,需要将可执行文件加载到内存,形成进程
3.一个程序可以同时存在多个进程
4.进程在内存空间中的布局就是进程映像,从低地址到高地址依次为
(1)代码区
(2)数据区
(3)bss区
(4)堆
(5)堆栈缓冲区、加载动态库
(6)栈
(7)命令行参数、环境列表

虚拟内存
1.每个进程都有各自相互独立的4G字节虚拟地址空间
2.用户程序中使用的都是虚拟地址空间中的地址,永远无法直接访问实际物理内存地址
3.虚拟内存到屋里内存的映射由操作系统动态维护
4.虚拟内存一方面保护了操作系统的安全,另一方面允许应用程序使用比实际物理内存更大的地址空间
5.4G进程地址空间分成两部分
(1)[0,3G]为用户空间
(2)(3G,4G]为内核空间
6.用户控件中的代码不能直接访问内核空间中的代码和数据,但可以通过系统调用进入内核态,简介的与系统内核交互
7.对内存的越界访问,获知试图访问没有映射到物理内存的虚拟内存,将导致段错误
8.用户空间对应进程,进程一切换,用户空间随之变化
9.每个进程的内存空间完全独立,不同进程之间交换虚拟内存地址是无意义的
10.标准库内部通过一个双向链表,管理在堆中动态分配的内存
11.虚拟内存到物理内存的映射以页(4K)为单位

内存管理APIs
1.增量方式分配虚拟内存
voId *sbrk(intptr_t increment)
increment取值:内存增量(以字节为单位)
0 - 获取末尾地址。
>0 - 增加内存空间。
<0 - 释放内存空间。

	内部维护一个指针,指向当前堆内存最后一个字节的笑一个位置。

2.修改虚拟内存块末尾地址
	int brk(void *end_data_segment)
	内部维护一个指针,指向当前堆内存最后一个字节的下一个文职
	brk函数根据指针参数设置该指针的位置
	若发现页耗尽或空闲,自动追加或取消页映射
	简单来说,sbrk(类似于malloc)分配内存brk释放内存(类似于free)

3.创建与销毁虚拟内存到物理内存或文件的映射
	创建函数mmap
		void* mmap (
			void*  start,  // 映射区内存起始地址,NULL系统自动选定,成功返回之
			size_t length, // 字节长度,自动按页(4K)对齐
			int    prot,   // 映射权限
			int    flags,  // 映射标志
			int    fd,     // 文件描述符
			off_t  offset  // 文件偏移量,自动按页(4K)对齐
		);

		成功返回映射区内存起始地址,失败返回MAP_FAILED(-1)。

销毁函数munmap
	int munmap (
		void*  start,  // 映射区内存起始地址
		size_t length, // 字节长度,自动按页(4K)对齐
	);
	
	成功返回0,失败返回-1。
	
	mmap/munmap底层不维护任何东西,只是返回一个首地址,所分配内存位于堆中
	mmap返回的地址,是虚拟内存地址,用于映射到文件中,而文件地址是物理内存
	文件的大小决定了能够操作虚拟内存的大小 
	如果文件为空,如果通过mmap映射之后进行读写操作会出现总线错误

文件空洞
在超越文件尾的文件位置写入数据,将在文件中形成空洞
文件空洞不占用磁盘空间,但被算在文件大小中

文件锁
1.读锁(共享锁)
一个文件可以有多个读锁
2.写锁(独占锁/排它锁)
一个文件只能有一个写锁
3.文件锁只在不同进程间起作用
通过锁同步多个进程对同一个文件的读写访问
4.当对一个文件上了读锁之后,不能再对其上写锁,但可以上读锁
对一个文件上了写锁之后,不能再对其上写锁或读锁

进程
1.进程与程序
(1)进程就是运行着的程序
(2)程序存储在磁盘上,包含可执行机器指令和数据的静态实体
进程是处于活动状态的计算机程序
2.进程的分类
(1)进程一般分为:交互进程、批处理进程和守护进程三类
(2)守护进程总是活跃的,一般在后台运行
守护进程一般由系统开机时通过脚本自动激活启动,
或者由超级用户root启动
3.查看进程
(1)ps
(2)ps aux
(3)ps -elf
(4)ps aux|grep a.out
(5)top
4.父进程、子进程、孤儿进程、僵尸进程
(1)在一个程序中,通过fork函数创建进程的进程称为父进程
(2)被父进程创建的进程称为子进程
子进程结束时会向父进程发送SIGCHLD(17)信号,父进程回收子进程资源
(3)父进程先于子进程结束,子进程成为孤儿进程,并被init进程收养
(4)子进程先于父进程结束,但父进程没有回收子进程相关资源,该子进程成为僵尸进程
5.进程标识符(进程ID)
(1)每个进程都有一个非负整数表示的唯一标识,即进程ID/PID
(2)这个ID在任何时刻都是唯一的,但可以重复使用,即当一个进程退出时,其他进程可以使用这个ID
6.创建进程函数 fork
(1)创建一个子进程,失败返回-1,成功返回子进程PID和0
(2)子进程是父进程的副本
拷贝父进程的数据段和堆栈段
共享父进程的代码段
(3)函数调用后父子进程各自运行,运行先后顺序不确定
(4)父子进程共享文件表,即赴京城的文件描述符也会被复制到子进程中,二者共享同一个文件表
7.进程创建函数vfor
功能与fork基本相同,区别为:
(1)调用vfork创建子进程时不复制父进程的地址空间
子进程通过exec函数族,直接启动另一个进程替换自身,提高创建效率
(2)vfork调用后,子进程先执行
8.进程的正常退出
(1)return
(2)exit
① atexit(func) on_exit(func)
进程结束前调用用上述函数注册的函数
② 父进程调用wait/waitpid函数返回status的低8位
9. 进程的异常终止
(1) 调用abort函数,产生SIGABRT信号
(2) 进程接收到某些信号
(3) 最后一个线程对”取消”请求做出响应

信号处理
1.不可靠信号(非实时信号)
(1)小于SIGRTMIN(34)的信号都是不可靠信号
(2)不支持排队,可能会丢失,进程可能只收到一次该信号
(3)进程每次处理完这些信号后,对相应信号的相应被自动恢复为默认动作
除非显示地通过signal函数重新设置一次信号处理程序
2.可靠信号(实时信号)
(1)位于[SIGRTMIN(34),SIGRTMAI(64)]区间的信号都是可靠信号
(2)支持排队,不会丢失
3.信号来源
(1)硬件
(2)软件(程序)
4.信号处理
(1)忽略
(2)终止进程
(3)终止进程同时产生core文件
(4)捕获并处理。当信号发生时,内核会调用一个实现注册好的信号处理函数
5.递送与未决
(1)当信号产生时,系统内核会在其所维护的进程表中,为特定的进程设置一个与该信号相对应的标志位,这个过程称为递送
(2)信号从产生到完成递送之间存在一定的时间间隔,处于这段时间间隔中的信号状态称为未决
6.信号屏蔽
当在进行一些任务时,如更新数据库,不希望进程被某些信号中断,此时可以暂时屏蔽这些信号,使其滞留在未决状态,等任务完成后再处理这些 信号
在信号处理函数的执行过程中,这个正在被处理的信号总是处于信号掩码中

进程间通信
进程间通信方式:
a.简单进程间通信: 命令行参数、环境变量、信号、文件
b.传统进程间通信: 有名管道/无名管道(fifo/pipe)
c.XSL进程间通信: 共享内存、消息队列、信号量
d.网络进程间通信: 套接字
IPC标识
(1)用于本地通信,通过设置一个唯一的IPC键值实现多个进程的会合
(2)使用函数ftok创建一个唯一IPC键值
key_t ftok(const char* pathname , int id);
Key_t key=ftok(“./”,100);
(3)IPC命令
1. 显示
ipcs -m - 显示共享内存(m: memory)
ipcs -q - 显示消息队列(q: queue)
ipcs -s - 显示信号量(s: semphore)
ipcs -a - 显示所有IPC对象(a: all)
2. 删除
ipcrm -m ID - 删除共享内存
ipcrm -q ID - 删除消息队列
ipcrm -s ID - 删除信号量

1.共享内存
	(1)创建/获取共享内存 
			int shmget (key_t key, size_t size, int shmflg); 
	(2)加载共享内存 
			void* shmat (int shmid, const void* shmaddr,int shmflg); 
	(3)卸载共享内存 
			int shmdt (const void* shmaddr);
	(4)销毁/控制共享内存 
			int shmctl (int shmid, int cmd, struct shmid_ds* buf);
2.消息队列
	(1)创建/获取消息队列 
			int msgget (key_t key, int msgflg); 
	(2)向消息队列发送消息 
			int msgsnd (int msqid, const void* msgp,size_t msgsz, int msgflg); 
	(3)从消息队列接收消息 
			ssize_t msgrcv (int msqid, void* msgp, size_t msgsz,
						long msgtyp, int msgflg);
	(4)销毁/控制消息队列 
			int msgctl (int msqid, int cmd, struct msqid_ds* buf); 
3.信号量
	(1)创建/获取信号量 
			int semget (key_t key, int nsems, int semflg); 
	(2)操作信号量 
			int semop (int semid, struct sembuf* sops,unsigned nsops); 
	(3)销毁/控制信号量 
			int semctl (int semid, int semnum, int cmd); 
			int semctl (int semid, int semnum, int cmd,union semun arg); 

8.网络通信
	(1)ISO/OSI七层网络协议模型
		①应用层 		application
		②表示层 		presentation
		③会话层 		session
		④传输层 		transport
		⑤网络层 		network
		⑥数据链路层	data link
		⑦物理层		pyhsical
	(2)TCP/IP协议族
		a.TCP(传输控制协议)面向连接的服务
		b.UDP(用户数据报协议)面向无连接的服务
		c.IP(互联网协议)信息传递机制
	(3)IP地址
		1) IP地址是Internet中唯一的地址标识 
			A. 一个IP地址占32位,正在扩充至128位。 
			B. 每个Internet包必须带IP地址。
		2) 点分十进制表示法 
			0x01020304 -> 1.2.3.4,高数位在左,低数位在右。
		3) IP地址分级 
			A级:0 + 7位网络地址 + 24位本地地址 
			B级:10 + 14位网络地址 + 16位本地地址 
			C级:110 + 21位网络地址 + 8位本地地址 
			D级:1110 + 28位多播(Muticast)地址
		4) 子网掩码 
			IP地址 & 子网掩码 = 网络地址 
			IP地址: 192.168.182.48 
			子网掩码:255.255.255.0 
			网络地址:192.168.182 
			本地地址:48
	(4)套接字socket
		1)创建套接字
		int socket (int domain, int type, int protocol);
		2)准备通信地址
			IP地址用于定位主机,端口号用于定位主机上的进程
			A. 基本地址类型
				struct sockaddr 
				{
					sa_family_t sa_family;   // 地址族
					char        sa_data[14]; // 地址值
				};
			B. 本地地址类型
				#include <sys/un.h>
				struct sockaddr_un 
				{
					sa_family_t sun_family; // 地址族
					char        sun_path[]; // 套接字文件路径
				};
				
			C. 网络地址类型
				#include <netinet/in.h>
				struct sockaddr_in 
				{
					// 地址族
					sa_family_t sin_family;
				
					// 端口号
					// unsigned short, 0-65535
					// 逻辑上表示一个参与通信的进程
					// 使用时需要转成网络字节序
					// 0-1024端口一般被系统占用
					// 如:21-FTP、23-Telnet、80-WWW
					in_port_t sin_port;
				
					// IP地址
					struct in_addr sin_addr;
				};
				struct in_addr
				{
					in_addr_t s_addr;
				};
				typedef uint32_t in_addr_t;
	
		3)将套接字和通信地址绑定在一起
			int bind (int sockfd, const struct sockaddr* addr,socklen_t addrlen);
		4)建立连接
			int connect (int sockfd, const struct sockaddr* addr,socklen_t addrlen);
9.TCP协议
	(1)三次握手
		(connect)SYN_SENT  Client  SYN  x    --->        Server LISTEN(accept)
		ESTABLISHED       Client  <--- ACK  x+1  SYN  y  Server SYN_RCVD 
		(connect retrun)     Client  ACK  y+1  --->        Server ESTABLISHED
		(acceptreturn)
	(2)四次分手
		(close)FIN_WAIT1   Client  FIN m   --->   Server  CLOSE_WAIT(passive close)
		FIN_WAIT2  Client  <---  ACK m+1  Server  (read return)
		TIME_WAIT  Client  <---  FIN n     Server  LAST_ACK(close)
		TIME_WAIT  Clinet  ACK n+1  --->   Server  CLOSE
	
	(3)面向连接,传输可靠,保证数据的完整性和有序性
		每个发送都有应答,若在时间窗口内没有收到应答,则重发
10.UDP协议
	面向无连接,传输不可靠,不保证数据的完整性和有序性
	发送不需要应答,因此效率高速度快

线程
1.基本概念
(1)线程就是程序的执行路线,是进程的子任务
(2)轻量级,不拥有独立的内存资源,共享进程的代码区、数据区、堆区、环 境变量和命令行参数、文件描述符、信号处理函数、当前目录、用户ID 和组ID等资源
(3)线程拥有自己独立的栈,因此有自己独立的局部变量
(4)一个进程可以同时拥有多个线程
(5)同一个进程的多个线程都在同一个地址空间内活动,因此相对于进程,线 程的系统开销小,任务切换快。
2.线程函数
(1)创建线程
int pthread_create (pthread_t* restrict thread, const pthread_attr_t* restrict attr, void* (start_routine) (void), void* restrict arg);
(2)等待线程
int pthread_join (pthread_t thread, void** retval);
等待thread参数所标识的线程结束,成功返回0,失败返回错误码。
(3)获取线程自身ID
pthread_t pthread_self (void);
成功返回调用线程的ID,不会失败。
(4)比较两个线程的ID
int pthread_equal (pthread_t t1, pthread_t t2);
(5)终止线程
void pthread_exit (void* retval);
3.线程同步
(1)概念
当多个线程同时访问其所共享的进程资源时,需要相互协调,以防止出现 数据不一致、不完整的问题,这就是线程同步。
(2)互斥量(互斥锁) pthread_mutex_t
1)类型
a)普通锁
b)检错锁
c)嵌套锁
d)默认锁
(3)屏障 ptread_barrier_t
(4)读写锁 pthread_rwlock_t
(5)自旋锁 pthread_spinlock_t
(6)信号量 sem_t
(7)条件变量 pthread_cond_t
4.多路复用IO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值