热门搜索 :
考研考公
您的当前位置:首页正文

大三下Linux期末考试复习笔记

来源:东饰资讯网

第一章 Linux操作系统基础

  1. Linux的版本:有两种不同的称呼,内核版本、发行版(教材P6)
  2. 需要掌握的内核版编号方式:这种编号方式用于1.0-2.6,数字由三部分组成:A.B.C
    1. A代表主版本号,只有内核发生很大变化是,才变化
    2. B代表次版本号,可以通过其判断该版本是否稳定,偶数->稳定版,奇数->开发版。
    3. C代表较小的末版本号,表示一些bug修复、安全更新、新特性和驱动的次数。

第二章 Linux平台项目开发环境

  1. vi的三种工作模式,插入模式、命令模式、末行模式(教材P26)
    1. 插入模式:也称为编辑模式,进入插入模式后,屏幕的最后一行会出现“编辑”或“insert”字样。要注意的是,刚启动vi时是处于命令模式下。笔者一般是按“i”键进入插入模式。
    2. 命令模式:等待用户输入命令的模式,类似于图像界面中用鼠标点击某些菜单选项的感觉。
    3. 末行模式:在命令模式下键入“:”,为了完成文档的一些辅助功能,q:若文档没有修改过直接退出vi,否则会有提示信息并且不会退出vi;wq:保存并退出;q!:直接退出,无论内容有没有修改,都不会保存。
  2. GCC编译器的基本用法(教材P30-P31)
    1. 源文件生成可执行文件
      gcc -o main main.c
      或
      gcc main.c -o mian
      
源文件生成可执行文件01.png 源文件生成可执行文件02.png
2. 源文件生成目标文件
    ```
    gcc -c main.c
    ```
源文件生成目标文件.png
3. 源文件生成汇编文件
    ```
    gcc -s main.c
    ```
源文件生成汇编文件.png
  1. Makefile文件的内容(教材P35)
    1. 语法格式
      目标文件:依赖文件列表
      <tab>更新目标文件使用的命令
      
    2. 举例说明:编译main.c
      main:main.o
          gcc -o main main.o
      main.o:main.c
          gcc -c main.c
      clean:
          rm main main.o
      
Makefile编写例子.png
make clean.png
3. 教材P49的Makefile,这个没什么好说的,就是个变量的替换(实在不能理解就背下来)
    ```
    OBJ=stuscore
    SRC=stuscore.c in.c out.c cal.c
    $(OBJ):$(SRC)
        gcc -o $@ $^
    clean:
        rm $(OBJ)
    ```

第三章 Linux程序设计初步

  1. C进程内存布局(这里参考教材P53),要注意的是:堆是动态分配的内存区域,大小不固定,可动态的增加(malloc函数)和释放(free函数);栈用来保存函数临时创建的局部变量(不包括函数内部的static变量),另外在函数被调用时,函数参数也会被压如发起调用函数的进程栈中,等待调用结束后,函数的返回值会被放到栈中。

  2. 特殊修饰变量的存储位置(教材P54)

    变量形式 存储位置
    auto变量
    stati全局变量 已初始化在数据段,未初始化在BSS
    extern变量 extern变量用于声明引用定义在别处的全局变量,该变量已经初始化在数据段,未初始化在BSS
    register变量 CPU寄存器
  3. 命令行参数(教材P56)

    • 用户在执行程序时输入的包含程序名称在内直到回车之前的所有数据成为命令行参数
  4. 环境变量修改(教材P60),修改环境变量的格式与定义环境变量的格式相同,对于export命令的使用也相同。如果修改变量的同时还需要包含原来的值,则需要事先引用原来的值,如PATH变量中保存了可执行文件的搜索路径,使用冒号分隔,原来保存了一些路径值,如果需要增加一个当前目录,则要进行如下修改:

    export PATH=$PATH:.
    
  5. 函数unsetenv,(教材P61)

    项目 描述
    头文件 #include <stdlib.h>
    原型 void unsetenv(const char *name);
    功能 删除一个环境变量
    参数 name:要删除的环境变量名
    返回值 执行成功时,返回0;失败时,返回-1,并设置errno
  6. 时间管理(教材P64)

    1. Linux内核提供的时间是从国际标准时间(UTC)公元1970年1月1日0时0分0秒开始以来经过的秒数,被称为日历时间,数据类型为time_t

    2. 系统调用time(教材P63)

      项目 描述
      头文件 #include <time.h>
      原型 time_t time(time_t *t);
      功能 得到当前的日期和时间
      参数 t:time_t类型指针,指向获得的当前日期和时间
      返回值 time_t类型,代表获得的当前时间
      备注 调用形式可以有两种,一种是通过参数获得,一种是通过返回值获得(如下方代码)
      time_t time;
      time = time(NULL); 或 time(&time);
      
    3. 函数ctime,(教材P64)

      项目 描述
      头文件 #include <time.h>
      原型 char *ctime(const time_t *t);
      功能 把time_t转换为本地时间字符串
      参数 t:time_t类型指针,代表要转换的time_t类型时间
      返回值 time_t类型,代表获得的当前时间
    4. 知识验证

      • 获取当前时间,按要求输出
      1. 通过结构体方式输出“年-月-日:时:分:秒:星期”
      2. 通过字符串输出


        time知识验证.png
  7. 项目:设置环境变量(教材P71)


    setenvvar.png

第四章 文件I/O

  1. UNIX文件系统结(教材P76)

    引导区(Boot Block) 超级块(Super Block) 索引节点表(Inode List) 数据区(Data Blocks)
  2. 。。(教材P80)

    八进制 描述
    S_ISUID 0004000 SUID权限
    S_ISGID 0002000 SUID权限
    S_ISVTX 0001000 sticky权限
    S_IRWXU 00700 文件主人权限掩码
    S_IRUSR 00400 主人有读权限
    S_IWUSR 00200 主人有写权限
    S_IXUSR 00100 主人有执行权限
    S_IRWXG 00070 同组用户权限掩码
    S_IRGRP 00040 同组用户有读权限
    S_IWGRP 00020 同组用户有写权限
    S_IXGRP 00010 同组用户有执行权限
    S_IRWXO 00007 其他用户权限掩码
    S_IROTH 00004 其他用户有读权限
    S_IWOTH 00002 其他用户有写权限
    S_IXOTH 00001 其他用户有执行权限
  3. 访问文件的内核数据结构(教材P82)

    1. 每个进程在简历好时,都默认打开三个文件:标准输入设备文件、标准输出设备文件、标准错误输出设备文件。这三个文件登记在用户打开文件描述服务表中的前三项。因此这三个文件的文件描述服务分别是0、1、2.Linux系统中定义了这三个文件描述符
      # define STDIN_FILENO 0     //标准输入设备文件
      # define STDOUT_FILENO 1    //标准输出设备文件
      # define STDERR_FILENO 2    //标准错误输出文件
      
  4. 文件基本I/O操作

    1. 系统调open/creat(教材P83)

      项目 描述
      头文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>
      原型 int open(const char *path,int flags); int open(const char *path,int flags,mode_t mode); int open(const char *path,mode_t mode);
      功能 按照flags打开path指定的文件,或者创建权限为mode的新文件path
      参数 path:要打开或创建的文件名(包名);flags:打开方式;mode当要创建一个新文件时mode指定权限
      返回值 成功时,返回一个问价描述符;失败时返回-1,并且errno为错误码
    2. 文件描述符(教材P85)。每个进程都有一个用户文件描述符表,用来记录该进程已经打开的文件。当一个进程通过open()打开一个文件时,系统根据path找到该文件的inode,校验该文件的属性信息是否可以打开。如果可以打开,则该进程的用户文件描述符表中查找最小可用表项的索引作为文件描述符返回。所以open函数总是得到一个最小可用的文件描述符。

    3. flags 含义
      O_RDWR 读写方式
      O_CREAT 如果path指定的文件不存在,就创建该文件
      O_TRUNC 如果path指定的文件是已经存在的普通文件,并且打开方式是可写的,就将文件长度截为0.对于FIFO文件或终端设备文件,该方式被忽略

      打开文件方式flags(教材P84)

      flags 含义
      O_RDWR 读写方式
      O_CREAT 如果path指定的文件不存在,就创建该文件
      O_TRUNC 如果path指定的文件是已经存在的普通文件,并且打开方式是可写的,就将文件长度截为0.对于FIFO文件或终端设备文件,该方式被忽略
  5. whence的取值(教材91)

    whence参数 | 读写指针移动方式 | 读写指针移动结果 
    ---|---|---
    SEEK_SET | 从文件开始位置移动 | 即为offset的值
    SEEK_CUR | 从文件当前位置开始移动 | 当前读写指针的值+offset
    SEEK_END | 从文件末尾位置移动 | 文件长度+offset
    
    1. 知识验证,同一个程序,两次打开同一个文件进行读写操作。(教材P93)
      • 为了证明:两次调用open函数得到的文件描述符不同


        fileopen.png

第五章(文件属性管理)

  1. 系统调用stat/fstat/lstat(教材P102)
    1. int stat(const char * file_name, stuct stat * buf);
    2. int fstat(int filedes, struct stat * buff);
    3. int lstat(const char * file_name, struct stat * buff);
    4. 功能描述:获取指定文件的文件属性,并将属性存入stat的结构体buff中
  2. 硬链接与符号链接(教材P107)
    • 硬链接和符号链接都是指向另一个已存在文件的链接,符号链接文件相当于Windows中的快捷方式
    1. 硬链接命令:ln 原文件 硬链接文件(不能对目录创建硬链接!!!)
    2. 符号链接命令:ln -s 原文件/目录 符号链接文件

第六章(目录文件管理)

  1. 函数readdir,(教材P124)
    1. 原型:struct dirent * readdir(DIR * dir)
    2. 功能:该函数从dir指向的目录文件中读取一个目录项,并返回一个指向该目录项的指针
    3. 参数:dir:指向要读取的目文件的指针,dir可以使用函数opendir()打开目录文件时得到
    4. 返回值,成功返回dirent结构体指针;失败或读到目录文件末尾,返回NULL

第七章(进程控制)

  1. 用户标识(教材P139)
  2. 系统调用fork,(教材P141)
    1. 原型:pid_t fork(void)
    2. 功能:创建一个子进程
    3. 参数:无
    4. 返回值:成功时,在父进程返回PID,在子进程返回0;失败时,返回-1并置错误代码errno
    5. 由父进程调用一次,但是返回值有两次。
    6. 用fork创建的子进程是父进程的复制品,子进程拥有父进程的数据空间、堆、栈的一份拷贝,父子进程不共享这部分存储空间
  3. 系统调用vfork(),(教材P149)
    1. 原型:pid_t vfork(void)
    2. 功能:创建一个子进程,并阻塞父进程
    3. 参数:无
    4. 返回值:成功时,在父进程返回PID,在子进程返回0;失败时,返回-1并置错误代码errno
    5. 由父进程调用一次,但是返回值有两次。
    6. 用vfork创建子进程,不会将父进程的数据空间复制到子进程中,子进程与父进程共享数据空间,父进程会等待子进程先执行。子进程中如果不调用exec函数,则需要调用_exit系统调用。
  4. 知识验证,通过waitpid等待指定的子进程结束(P158)


    互斥锁.jpg

第八章(线程)

  1. 线程对比进程(教材P169)

    1. 创建新线程系统开销小

    2. 多线程间共享地址空间,线程间切换效率高

    3. 通信方面,线程间通信更方便和省时

    4. 可以提高程序响应速度

    5. 多线程可以提高多核cpu执行效率

    6. 在大型程序中,采用多线程设计可以改善程序结构

    7. 需要频繁创建和销毁就选择多线程

    8. 需要大量计算,优先考虑多线程

    9. 并发处理间的相关性强的,优先考虑多线程,反之,优先考虑多进程


    10. 若编程和调试都相对简单地程序,可以优先开了多进程

    11. 若对可靠性有一定要求,多进程会更加安全可靠,因为多线程共享进程的地址空间,对资源的同步、互斥的访问时易产生错误

  2. 知识验证,利用互斥锁,实现多线程对临界资源的同步互斥问题(教材P177)


    177.jpg

第九章(信号与管道)

  1. 什么是信号(教材P186)
    • 在Linux系统中,信号是一个32位整型值,代表一个简单信息。每个信号都是以一个SIG开头的名字,实际上是系统定义的宏,如SIGINT代表中断信号,其值为2
  2. 系统调用alarm,(教材P191)
    1. 原型:unsigned int alarm(unsigned int seconds);
    2. 功能:设置一个定时器
    3. 参数(重点):seconds为定时器的时间
    4. 返回值(重点):返回上一个定时器剩余时间,如果没有其他定时器则返回0
    5. 解释返回值;每个进程只拥有一个定时器时间,如果在调用alarm之前已经设置了定时器且还没有超时,则此次alarm调用返回上一次所设时间的剩余值,并重新设置定时器时间。
  3. 进程如何响应信号(教材P192)
    1. 忽略信号
    2. 执行系统默认动作
    3. 捕捉信号
  4. 管道(教材P208)
    • 我们这里讨论的管道,也称为无名管道,也就是说通信的进程不需要为管道命名就可以访问,通过管道传数据。使用管道通信的两个进程一定要有共同的祖先。
  5. FIFO也称为命名管道。允许不想管进程通信。(教材P214)

第十章(略)

第十一章(网络编程)

  1. 字节序(教材P251)


    字节序.jpg
  2. 套接字地址结构:ip+port(教材P255)

  3. 面向连接(tcp)套接字通信过程(教材P257)


    tcp.jpg
  4. 面向无连接(udp)套接字通信过程 (教材P258)
    尴尬!这个拍的图片不见了,就参考参考教程上的吧!

  5. TCP和UDP的服务器端代码实现(重点)(教材P269-P273)

// TCP server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

# define SERVERPORT 3333 // 服务器端口号
# define BACKLOG 10 // 最大同时连接请求数


int main(int argc, char const *argv[])
{
    int sockfd, connfd; // sockfd:监听套接字;connfd:链接套接字
    struct sockaddr_in my_addr; // 本机地址
    struct sockaddr_in remote_addr; // 客户端地址
    int sin_size, val = 1, status;

    //创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);  //SOCK_STREAM表示使用TCP
    if (sockfd == -1)
    {
        perror("socket");
        exit(1);
    }
    // 设置地址端口可以重用
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
    // 设置本地地址信息
    my_addr.sin_family = AF_INET; // 协议簇使用ipv4
    my_addr.sin_port = htons(SERVERPORT); // 端口号
    my_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // ip地址
    bzero(&(my_addr.sin_zero),8); // 填充0 
    // 绑定地址到套接字描述符上
    status = bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
    if (status == -1)
    {
        perror("bind");
        exit(1);
    }
    // 在地址端口监听
    status = listen(sockfd,BACKLOG);
    if (status == -1)
    {
        perror("listen");
        exit(1);
    }
    while (1)
    {
        sin_size = sizeof(struct sockaddr_in);
        // 等待客户端的接入
        connfd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size);
        if (connfd == -1)
        {
            perror("accept");
            exit(1);
        }
        // 当客户端接入了,就可以做收发操作了...
        printf("有客户端接入");
    }
    return 0;
}

// DUP server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

# define SERVERPORT 3333 // 服务器端口号
# define MAXDATASIZE 100

int main(int argc, char const *argv[])
{
    int sockfd; // sockfd:监听套接字
    struct sockaddr_in server;
    struct sockaddr_in client;
    int sin_size;
    int num;
    char msg[MAXDATASIZE];
    char sbuf[100] = " ";
    return 0;
    // 创建UDP套接字
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)  //SOCK_DGRAM表示使用UDP
    {
        perror("socket");
        exit(1);
    }
    // 设置本地地址信息
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET; //协议簇使用ipv4
    server.sin_port = htons(SERVERPORT); //
    server.sin_addr.s_addr = htonl(INADDR_ANY); //
    // 绑定地址到套接字描述符上
    if (bind(sockfd,(struct sockaddr *)&server, sizeof(struct sockaddr)) == -1)
    {
        perror("bind");
        exit(1);
    }
    sin_size = sizeof(struct sockaddr_in);
    while (1)
    {
        // 从监听端口读出数据
        num = recvfrom(sockfd, msg, MAXDATASIZE,0,(struct sockaddr*)&client, &sin_size);
        if (num < 0)
        {
            perror("recvfrom");
            exit(1);
        } 
        msg[num] = '\0'; // 添加消息结束符
        // 后面就可以根据client得到客户端的信息,即可实现通信。
    }
}

Top