UNIX/LINUX C总结

本文详细介绍了Unix/Linux系统下C语言编程的特点,包括gcc编译过程、预处理指令、库文件类型、错误处理方法以及内存管理、进程管理、信号处理、进程间通信等多个方面,深入探讨了Unix/Linux环境下的C语言编程技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Unix/linux  C(uc)与标准C语言最大的区别在于,标准C只是一种编程语言,而在此基础上还依赖于具体的操作系统,脱离了unix/linux系统的uc在其他地方可能不被识别。

(1)Unix/Linux系统的基本概述

用gcc将源文件翻译为可执行文件过程:

  预处理:主要宏替换,头文件替换。

宏替换:#define用一个自定义的量代替一个数,如果要修改这个量的值,只要在最初的定义处修改即可。同时也定义了一些预定义宏:

__FILE__  -主要用于获取当前文件名%s
     __LINE__  -主要用于获取当前宏所在的行号 %d
     __DATE__  -主要用于获取日期信息  %s
     __TIME__  -主要用于获取时间信息  %s
头文件替换:#include “a.h”表示先从当前程序所在目录开始寻找,然后去系统默认目录,#include <a.h>表示表示从系统默认所在目录开始寻找。

预处理指令:全部都以#开头

#pragma GCC dependency 文件名
         =>表示当前文件依赖于指定的文件名,如果指定文件名的最后一次修改时间晚于当前文件,则产生警告信息

#pragma pack(整数n)超过4按4计算
       =>主要用于设置对齐和补齐方式
         #warining 字符串 
  => 表示产生一个警告信息
         #error 字符串
  => 表示产生一个错误信息
编译:检查语法的错误,同时将源文件翻译为汇编文件.s

           汇编:将汇编文件转化为目标文件.o

链接:若编译时遇到调用其他文件的函数或变量时,会留下一个接口,链接部分则是找到这些接口要调用的函数或变量所在位置,将这些目标文件整合到一起,转化为可执行文件。

库文件:

             一般为了调用者或者使用者的方便,会将完成一个具体功能是所有.o文件打包成一个库,调用或使用时只需要这个库文件和其对应的头文件即可。库文件分为两种:静态库和动态共享库。

              静态库:使用这个库也就是链接时,如果要调用其他文件的函数或变量,会直接拷贝过来,所以目标文件会很大,但是运行时可以脱离静态库,不需要各种跳转。

              动态共享库:使用这个库也就是链接时,如果要调用其他文件的函数或变量,会将要调用的函数或变量所在的地址拷贝过来,所以目标文件小,但是运行时不能脱离这个库,要各种跳转。可通过dlopen函数打开/加载共享库,dlsym函数在共享库中查找指定的函数地址信息。

函数出错:

1.对于返回值为int的函数,返回值是负数则代表出错,所以如果int型函数要返回一个负数值一般通过一个指针带出去,而返回值只表示是否出错,-1为出错,0为正常,返回值是指针则NULL表示出错,正确则是要返回的地址。

2.#include<error.h> errno是一个int型的全局变量,当程序运行出错会自动将出错原因序号值赋给errno。可以通过sterror(errno)输出对应errno的出错原因,也可以直接用perror(char *s)打印出&s:最近一次出错原因

         main函数的原型:
int main(int argc,char* argv[]) 可以外部设定运行这个程序时的命令行参数值和每一个参数的位置
(2)Unix/Linux系统下的内存管理技术

         在对文件的打开,读,写这些操作中,标C与uc相比效率更高,因为标C有标准输入输出的缓冲区,对于uc是用文件描述符来进行读写,文件描述符是一个整数,它在内核里对应着一个文件表,存储了当前文件的各种信息,当close()时是将该整数与文件表关系脱离,如果该文件表不再对应任何一个文件描述符则删除。

         文件描述符是从3开始,0,1,2分别代表标准输入输出和标准错误。

         利用fcntl函数可以对该文件描述符复制,获取状态,实现文件锁。
(3)Unix/Linux系统下的进程管理

程序最开始只有一个进程,也就是父进程运行,当遇到fork()函数时会创建一个新的进程叫子进程,同时fork之后的程序会由父进程和子进程同时开始执行,但我们当然希望他们分工干不同的事情,因此通过fork之后的返回值来判断是父进程还是子进程,若为0,则表示当前是子进程,若不为0则表示当前是父进程,同时返回的值表示子进程的进程号,PID表示进程编号,用getpid函数获取。

使用fork创建的子进程,会将父进程的内存区域除了代码区复制一遍,因此子进程的运行是在fork之前的运行结果基础之上开始的,但是之后子进程和父进程分别有各自的内存区域,除了代码区会共享。

父进程可利用wait函数来挂起当前进程,直到一个子进程结束并返回子进程结束运行状态。

Vfork()函数与fork()的区别是创建的子进程会直接占用父进程的内存区域而不是复制,导致父进程暂时挂起,一般与exec系列的函数搭配使用让子进程去执行一个别的程序,成为一个全新的进程,同时解除父进程的阻塞状态。如果用fork+exec则要复制一遍内存区域,而对于马上执行其他程序的子进程来说是多此一举。
(4)Unix/Linux系统下的信号处理

信号本质上来说就是一种软件中断,信号可以通过键盘(Ctrl+C等等)、程序出错(段错误信号11 SIGSEGV)、特定发送信号的函数(kill(),sleep()等等)来发出,信号是异步的,对于程序而言并不知道什么时候信号会到来,但一旦收到一个信号会立即进行处理。处理的方式有三种,默认处理(终止程序)、忽略处理、自定义处理(运行特定的函数),可通过signal函数进行设定。也可通过特定函数将所有信号屏蔽,待恢复之后再查看屏蔽期间收到过的信号。
(5)Unix/Linux系统下的进程间的通信

重点:

通信的主要方式

(1)文件

(2)信号

(3)管道

(4)共享内存

(5)消息队列(重点)

(6)信号量集      

(7)网络通信(重点)

1.文件

         多个进程可通过访问同一个文件来进行通信

2.信号

         不同进程间可通过kill()函数等向其他进程发送信号

3.管道

         管道的本质还是文件,分为有名管道(任意通信)和无名管道(父子进程间通信)

         有名管道:  mkfifo a.pipe(创建管道)

                                     echo hello > a.pipe(数据不能写进去)

另外一个中断中输入:

                                     cat a.pipe(数据传递到这里)

                                因此管道实际上并不能存储数据,它只是一个传递数据的通道

无名管道:int pipe(intpipefd[2])返回两个文件描述符,其中pipefd[0]表示是读端,pipefd[1]表示是写端。

4.共享内存

                   本质上是内核维护的一块内存区域,两个进程可以共同使用这一块内存区域来进行通信。过程开始与消息队列类似要生成一个key值,通过key值创建或获取共享内存地址,用shmat()函数将共享内存地址挂接到本进程地址空间上,使用完毕后要脱接。

5.消息队列

                   将消息放到消息队列中后,由其他进程进行读取,这个消息队列会一直持续到内核重启,如何获取消息队列是通过key值,双方通过约定一个文件路径和ID号,用ftok()来生成一个相同key值,通过该key值就能用msgget()函数获取到消息队列号,类似于文件描述符,双方可通过该消息队列进行通信。

6.信号量集

                   信号量集本质上是一个计数器,多个进程要同时访问一个共享资源时,可设定一个信号量集表示当前可访问共享资源的进程数,每当有一个进程要访问资源,该信号减1,当一个进程访问完毕该信号加1,当该信号变为0时表示访问该资源的进程数已达最大值,要等待。

7.网络通信

                   常用的网络协议:

         TCP:传输控制协议,面向连接的协议,类似于打电话

         UDP:用户数据报协议,非面向连接的协议,类似于发短信

IP:通过IP可以定位到具体的一台电脑

端口:通过端口号可定位到这台电脑上的一个具体运行的进程

Socket:参考上篇博客

(6)Unix/Linux系统下的多线程编程

                   线程隶属于进程,进程是重量级单位,每当创建一个新的进程要新开辟一块内存,每个进程有独立的内存区域,而线程是轻量级单位,新创建的线程共享内存资源,但每个线程都有独立的栈区。多个线程相互独立又相互影响,当访问同一个文件时一般采用互斥锁。

                   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值