Linux文件、进程、网络编程全解析,自制笔记一万字!!

文件编程

内容概览

包含文件系统原理及访问机制、文件在内核中的管理机制、文件信息节点 inode、文件的共享、文件权限(各种用户对其权限)等内容。

应用场景
  • 实际应用:账单、游戏进度、配置文件等。
  • 核心需求:通过代码操作文件,实现文件创建、打开、编辑等自动化执行。
文件操作对比
  • Windows 手动修改文件:如编写 Word 文档的流程。
  • Linux 操作流程:打开 / 创建文档→编辑文档→保存文档→关闭文档。
Linux 文件操作 API

操作系统提供一系列 API 实现自动化操作,包括:

  • 打开:open
  • 读写:write/read
  • 光标定位:lseek
  • 关闭:close
打开 / 创建文件

  1. 函数原型

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);
    int creat(const char *pathname, mode_t mode);
    
  2. 描述open()通过路径名打开文件,返回文件描述符(非负整数),用于后续系统调用(如readwrite等)。成功返回的文件描述符是进程中当前未使用的最小非负整数。

  3. 参数说明

    • pathname:要打开的文件名(含路径,缺省为当前路径)。
    • flags
      • 必选权限(仅能指定一个):O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(可读可写)。
      • 可选参数:
        • O_CREAT:文件不存在则创建,需同时指定mode
        • O_EXCL:与O_CREAT同时使用时,若文件已存在则出错。
        • O_APPEND:每次写操作追加到文件尾端。
        • O_TRUNC:若文件有内容且以只读 / 只写成功打开,将长度截短为 0。
    • mode:仅当flagsO_CREAT时有效,指定新文件的访问权限。
  4. 创建文件creat函数

    运行

    int creat (const char *filename, mode_t mode)
    
     
    • filename:要创建的文件名(含路径,缺省为当前路径)。
    • mode:创建模式(宏表示与对应数字):
      • 可读:S_IRUSR(4)
      • 可写:S_IWUSR(2)
      • 可执行:S_IXUSR(1)
      • 可读、写、执行:S_IRWXU(7)
写入文件
  1. 函数原型

    运行

    #include <unistd.h>
    ssize_t write(int fd, const void *buf, size_t count);
    
  2. 描述:从缓冲区buf向文件描述符fd对应的文件写入最多count字节。
  3. 返回值:成功返回写入的字节数(0 表示未写入);失败返回 - 1,errno被设置。
    • 写入字节可能少于count(如存储空间不足、被信号中断等)。
    • 对可定位文件,写入从当前偏移量开始,偏移量随写入字节数增加;若以O_APPEND打开,写入前偏移量被设为文件尾,偏移量调整和写入为原子操作。
读取文件
  1. 函数原型
    #include <unistd.h>
    ssize_t read(int fd, void *buf, size_t count);
    
  2. 描述:从文件描述符fd对应的文件读取最多count字节到缓冲区buf
  3. 返回值:成功返回读取的字节数(0 表示文件结束),文件位置随字节数推进;失败返回 - 1,errno被设置。
    • 读取字节可能少于count(如接近文件尾、从管道 / 终端读取、被信号中断等)。
文件 “光标” 位置(lseek
  1. 函数原型
    #include <sys/types.h>
    #include <unistd.h>
    off_t lseek(int fd, off_t offset, int whence);
    
  2. 描述:重新定位文件读写偏移量,根据whence调整:
    • SEEK_SET:偏移量设为offset字节。
    • SEEK_CUR:偏移量设为当前位置加offset字节。
    • SEEK_END:偏移量设为文件大小加offset字节。
关闭文件(close
  1. 函数原型
    #include <unistd.h>
    int close(int fd);
    
  2. 描述:关闭文件描述符fd,使其不再指向任何文件并可重用。释放关联资源,若为最后一个引用且文件已被unlink,则删除文件。
  3. 返回值:成功返回 0;失败返回 - 1,errno被设置。
文件描述符
  1. 内核通过文件描述符(非负整数)引用所有打开文件。打开 / 创建文件时,内核向进程返回文件描述符,用于标识文件并传递给readwrite等函数。
  2. 惯例:文件描述符 0(标准输入,STDIN_FILENO)、1(标准输出,STDOUT_FILENO)、2(标准错误输出,STDERR_FILENO)。
  3. 进程中,文件描述符与内核维护的动态文件数据结构绑定,作用域仅限当前进程。
文件编程一般步骤
  1. 打开 / 创建文件:获取文件描述符。
  2. 读取 / 写入文件:操作内存中的动态文件。
  3. 关闭文件:同步动态文件到块设备的静态文件,释放资源。
  4. 原理:
    • 静态文件:存于块设备的文件系统中。
    • 动态文件:打开文件时,内核在内存中创建的数据结构,映射静态文件内容,读写操作基于动态文件。
    • 设计原因:内存操作(字节单位、随机访问)比块设备操作(按块读写)更灵活。
Linux 文件管理简述

(对应图片内容未明确,暂空)

文件编程练手
  1. 实现 Linux 的cp命令代码。
  2. 配置文件修改:如修改包含SPEED=5LENG=100SCORE=90LEVEL=95的配置文件。
其他问题
  1. 如何用文件记录一个结构体?(未提供具体内容)
  2. 函数对比:fopenfreadfwritefseekfclosefgetcfputcfeof与前述 API 的区别(参考链接:总结open与fopen的区别 - NickyYe - 博客园)。
扩展概念

Linux 中 “一切皆文件”,包括文件系统(文件夹 / 文件)、硬件设备、管道、数据库、Socket 等。

进程

进程关键概念
  1. 什么是程序,什么是进程,有什么区别?
  2. 如何查看系统中有哪些进程?
  3. 什么是进程标识符?
  4. 什么叫父进程,什么叫子进程?
  5. C 程序的存储空间是如何分配?
问题与解答
  1. 什么是程序,什么是进程,有什么区别?

    • 程序:静态的概念,如通过gcc xxx.c –o pro在磁盘中生成的pro文件。
    • 进程:程序的一次运行活动,即程序运行起来后,系统中新增的活动实体。
  2. 如何查看系统中有哪些进程?

    • 使用ps指令,实际工作中常配合grep查找特定进程。
    • 使用top指令,类似 Windows 任务管理器。
  3. 什么是进程标识符?

    • 每个进程都有一个非负整数表示的唯一 ID,称为pid(类似身份证)。
    • 特殊进程 ID:
      • pid=0:交换进程(swapper),作用是进程调度。
      • pid=1init进程,作用是系统初始化。
    • 编程中可通过getpid函数获取自身进程标识符,getppid获取父进程标识符。
  4. 什么叫父进程,什么叫子进程?

    • 若进程 A 创建了进程 B,则 A 称为父进程,B 称为子进程。
    • 父子进程是相对概念,类似人类的父子关系。
  5. C 程序的存储空间是如何分配?

    • 从高地址到低地址依次为:命令行参数和环境变量、栈、堆、未初始化的数据(bss 段)、初始化的数据、正文段。
    • 各段说明:
      • 正文段:CPU 执行的机器指令部分,可共享且通常只读。
      • 初始化数据段:包含程序中需明确赋初值的变量,如int maxcount =99;
      • 非初始化数据段(bss 段):程序开始执行前,内核将此段数据初始化为 0 或空指针,如long sum[1000];
      • :存放自动变量及函数调用时需保存的信息(如返回地址、寄存器值),支持函数递归调用。
      • :用于动态存储分配,位于非初始化数据段和栈之间。
进程创建实战
  1. 使用fork函数创建进程

    • 函数原型:pid_t fork(void);
    • 返回值:
      • 调用成功:返回两次,子进程中返回 0,父进程中返回子进程 ID。
      • 调用失败:返回 - 1。
  2. fork创建子进程的一般目的

    • 父进程复制自己,使父子进程同时执行不同代码段(如网络服务中,父进程等待请求,子进程处理请求)。
    • 进程需执行不同程序(如 shell 中,子进程fork后立即调用exec)。
  3. fork编程说明

    • fork创建的子进程是父进程的副本,子进程获得父进程数据空间、堆和栈的副本(现代实现采用写时复制技术,避免完全复制)。
    • 父子进程共享正文段。
  4. vfork函数与fork的区别

    • 关键区别一:vfork直接使用父进程存储空间,不进行拷贝。
    • 关键区别二:vfork保证子进程先运行,子进程调用exit退出后,父进程才执行。
进程退出
  1. 正常退出

    • main函数调用return
    • 进程调用exit()(标准 C 库函数)。
    • 进程调用_exit()_Exit()(系统调用)。
    • 补充:最后一个线程返回;最后一个线程调用pthread_exit
  2. 异常退出

    • 调用abort
    • 进程收到某些信号(如ctrl+C)。
    • 最后一个线程对取消请求做出响应。
等待子进程
  1. 等待原因

    • 父进程需等待子进程退出并收集其退出状态,否则子进程退出状态不被收集,会变成僵死进程(僵尸进程)。
  2. 相关函数

    • waitwaitpid
      • 函数原型:

        c

        运行

        #include <sys/types.h>
        #include <sys/wait.h>
        pid_t wait(int *status);
        pid_t waitpid(pid_t pid, int *status, int options);
        
      • 区别:wait使调用者阻塞;waitpid可通过选项设置不阻塞。
      • status参数:非空时,子进程退出状态存于其指向的地址;为空时,不关心退出状态。
      • waitpidpid参数作用:
        • pid==-1:等待任一子进程(与wait等效)。
        • pid>0:等待进程 ID 与pid相等的子进程。
        • pid==0:等待组 ID 等于调用进程组 ID 的任一子进程。
        • pid<-1:等待组 ID 等于pid绝对值的任一子进程。
  3. 检查终止状态的宏(表 8-1)

    说明
    WIFEXITED(status)若为正常终止子进程的状态,则为真;可通过WEXITSTATUS(status)取子进程退出参数的低 8 位
    WIFSIGNALED(status)若为异常终止子进程的状态(接到不捕捉的信号),则为真;可通过WTERMSIG(status)取终止信号编号
    WIFSTOPPED(status)若为当前暂停子进程的状态,则为真;可通过WSTOPSIG(status)取暂停信号编号
    WIFCONTINUED(status)若为作业控制暂停后继续的子进程状态,则为真(仅用于waitpid
孤儿进程
  • 父进程在子进程之前结束,子进程称为孤儿进程。
  • Linux 中,init进程会收留孤儿进程,成为其新的父进程。
exec族函数
  1. 函数特点

    • 执行成功后不会返回;调用失败时,设置errno并返回 - 1,从原程序调用点继续执行。
    • 参数说明:
      • path:可执行文件的路径名。
      • arg:可执行程序所带参数,第一个参数为可执行文件名(无路径时需以NULL结束)。
      • file:若包含/则视为路径名,否则按PATH环境变量搜寻可执行文件。
    • 函数名含义辅助记忆:
      • l:使用参数列表。
      • p:使用文件名,从PATH环境变量寻找可执行文件。
      • v:需构造指向各参数的指针数组,将数组地址作为参数。
      • e:多envp数组,使用新环境变量代替调用进程的环境变量。
  2. 作用

    • 让进程执行不同的程序(如 shell 中,子进程fork后立即调用exec)。
  3. fork配合使用

    • 例如:父进程检测到输入为 1 时,创建子进程并通过exec修改配置文件的字段值。
system函数
  • 功能:执行 shell 命令。
  • 函数原型:#include <stdlib.h> int system(const char *command);
  • 返回值:
    • 成功:返回进程的状态值。
    • sh不能执行时:返回 127。
    • 失败:返回 - 1。
  • 参考链接:linux system函数详解 - 南哥的天下 - 博客园
popen函数
其他参考链接

 

网络编程

TCP/UDP 对比
  1. 连接性:TCP 面向连接(如打电话需先拨号);UDP 无连接,发送数据前无需建立连接。
  2. 可靠性:TCP 提供可靠服务(数据无差错、不丢失、不重复、按序到达);UDP 尽最大努力交付,不保证可靠交付。
  3. 数据处理:TCP 面向字节流(将数据视为无结构字节流);UDP 面向报文。UDP 无拥塞控制,网络拥塞时不降低发送速率(适用于实时应用如 IP 电话、视频会议)。
  4. 连接方式:每条 TCP 连接仅点到点;UDP 支持一对一、一对多、多对一、多对多交互通信。
  5. 首部开销:TCP 首部开销 20 字节;UDP 首部开销仅 8 字节。
  6. 通信信道:TCP 为全双工可靠信道;UDP 为不可靠信道。
端口号作用
  • 一台主机可通过 IP 地址提供多种服务(如 Web、FTP、SMTP 等),仅靠 IP 地址无法区分,需通过 “IP 地址 + 端口号” 识别。
  • 端口是访问通道,服务器通过知名端口号被识别,例如:
    • FTP 服务器的 TCP 端口号为 21。
    • Telnet 服务器的 TCP 端口号为 23。
    • TFTP 服务器的 UDP 端口号为 69。
字节序
  1. 定义

    • 小端字节序(Little endian):数据低位字节存于内存低地址,高位字节存于高地址(如 0x01020304 在内存中存储为 04 03 02 01)。
    • 大端字节序(Big endian):数据高位字节存于内存低地址,低位字节存于高地址(如 0x01020304 在内存中存储为 01 02 03 04)。
    • 网络字节序:采用大端字节序。
    • 注:x86 系列 CPU 使用小端字节序。
  2. 字节序转换 API

    c

    运行

    #include <netinet/in.h>
    uint16_t htons(uint16_t host16bitvalue);  // 主机16位字节序转网络字节序
    uint32_t htonl(uint32_t host32bitvalue);  // 主机32位字节序转网络字节序
    uint16_t ntohs(uint16_t net16bitvalue);   // 网络16位字节序转主机字节序
    uint32_t ntohl(uint32_t net32bitvalue);   // 网络32位字节序转主机字节序
    
     
    • 缩写说明:h(host,主机)、n(net,网络)、s(short,2 字节)、l(long,4 字节)。
    • 可使用INADDR_ANY让操作系统自动获取地址。
服务器与客户端交互基础
  • 服务器:指定协议(TCP/UDP)、IP 地址(楼号)、端口号(房间号),并监听连接请求。
  • 客户端:获取服务器 IP 和端口号,发起连接。
Socket 服务器和客户端开发步骤
  1. 创建套接字
  2. 为套接字绑定信息(IP 地址和端口号)。
  3. 服务器监听网络连接。
  4. 服务器接受客户端连接。
  5. 数据交互。
  6. 关闭套接字,断开连接。
关键函数与结构
  1. 创建套接字(socket函数)

    c

    运行

    int socket(int domain, int type, int protocol);
    
     
    • 参数
      • domain:协议族(如AF_INET为 IPv4,AF_INET6为 IPv6,AF_UNIX为 Unix 域等)。
      • type:套接字类型(SOCK_STREAM为 TCP 流式套接字,SOCK_DGRAM为 UDP 数据报套接字,SOCK_RAW为原始套接字)。
      • protocol:协议(通常为 0,选择type对应的默认协议,如IPPROTO_TCP为 TCP,IPPROTO_UDP为 UDP)。
  2. 地址结构

    • 通用结构(struct sockaddr

      c

      运行

      struct sockaddr {
          unsigned short sa_family;  // 协议族
          char sa_data[14];          // IP+端口
      };
      
    • IPv4 专用结构(struct sockaddr_in

      c

      运行

      struct sockaddr_in {
          sa_family_t sin_family;     // 协议族
          in_port_t sin_port;         // 端口号(网络字节序)
          struct in_addr sin_addr;    // IP地址结构体
          unsigned char sin_zero[8];  // 填充,与`sockaddr`对齐
      };
      
  3. 地址转换 API

    • int inet_aton(const char* straddr, struct in_addr *addrp);:将字符串 IP(如 “192.168.1.123”)转为网络格式。
    • char* inet_ntoa(struct in_addr inaddr);:将网络格式 IP 转为字符串形式。
  4. 监听连接(listen函数)

    c

    运行

    #include <sys/types.h>
    #include <sys/socket.h>
    int listen(int sockfd, int backlog);
    
     
    • 功能:设置服务器套接字为监听模式,规定最大连接队列长度。
    • 参数
      • sockfd:服务器套接字描述符。
      • backlog:请求队列允许的最大请求数(内核维护未完成连接队列和已完成连接队列)。
  5. 接受连接(accept函数,服务器端)

    • 用于从已完成连接队列中接收客户端连接,返回新的套接字描述符用于数据交互。
  6. 发起连接(connect函数,客户端)

    c

    运行

    #include <sys/types.h>
    #include <sys/socket.h>
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    
     
    • 功能:客户端与服务器建立连接。
    • 参数
      • sockfd:客户端套接字描述符。
      • addr:服务器地址结构指针。
      • addrlen:地址长度(sizeof(struct sockaddr))。
    • 返回值:成功返回 0,失败返回 - 1。
  7. 数据收发函数

    • 基础函数(read/write

      c

      运行

      ssize_t write(int fd, const void* buf, size_t nbytes);  // 发送数据
      ssize_t read(int fd, void *buf, size_t nbyte);         // 接收数据
      
       
      • 返回实际读写的字节数,出错返回 - 1。
    • TCP 专用(send/recv

      c

      运行

      ssize_t send(int s, const void *msg, size_t len, int flags);  // 发送数据
      ssize_t recv(int s, void *buf, size_t len, int flags);        // 接收数据
      
       
      • 仅用于已连接的套接字,flags一般为 0。
    • 其他函数:readv/writevrecvmsg/sendmsgrecvfrom/sendto等。
总结

网络编程核心是通过 Socket 接口实现 TCP/UDP 通信,需关注字节序转换、地址绑定、连接管理及数据收发等环节,根据应用场景选择合适的协议(TCP 适用于可靠传输,UDP 适用于实时性要求高的场景)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小范好好学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值