嵌入式知识点总结

Linux常见命令

1. `ls` - 列出目录内容

   - 基本用法:`ls [选项] [目录]`

   - 常见选项:

     - `-l`:以长格式显示文件信息

     - `-a`:显示所有文件,包括隐藏文件

     - `-h`:以人类可读的格式显示文件大小

2. `cd` - 更改当前工作目录

   - 基本用法:`cd [目录路径]`

   - 示例:

     - `cd /home/user`:切换到`/home/user`目录

     - `cd ..`:切换到上一级目录

     - `cd ~`:切换到当前用户的主目录

3. `pwd` - 显示当前工作目录路径

   - 基本用法:`pwd`

4. `mkdir` - 创建新目录

   - 基本用法:`mkdir [选项] 目录名`

   - 常见选项:

     - `-p`:递归创建目录,包括父目录

5. `rm` - 删除文件或目录

   - 基本用法:`rm [选项] 文件或目录`

   - 常见选项:

     - `-r`:递归删除目录

     - `-f`:强制删除,不提示确认

6. `cp` - 复制文件或目录

   - 基本用法:`cp [选项] 源文件 目标文件`

   - 常见选项:

     - `-r`:递归复制目录

     - `-f`:覆盖已存在的目标文件

7. `mv` - 移动或重命名文件或目录

   - 基本用法:`mv [选项] 源文件 目标文件`

   - 常见选项:

     - `-i`:交互式操作,提示确认

8. `cat` - 显示文件内容

   - 基本用法:`cat [选项] 文件`

   - 常见选项:

     - `-n`:显示行号

9. `grep` - 在文件中搜索匹配的文本

   - 基本用法:`grep [选项] 模式 文件`

   - 常见选项:

     - `-i`:忽略大小写

     - `-r`:递归搜索目录下的文件

     - `-v`:显示不匹配的行

10. `head` - 显示文件开头部分

    - 基本用法:`head [选项] 文件`

    - 常见选项:

      - `-n`:指定显示的行数

11. `tail` - 显示文件结尾部分

    - 基本用法:`tail [选项] 文件`

    - 常见选项:

      - `-n`:指定显示的行数

      - `-f`:实时追踪文件内容

12. `wc` - 统计文件中的行数、字数和字符数

    - 基本用法:`wc [选项] 文件`

    - 常见选项:

      - `-l`:显示行数

      - `-w`:显示字数

      - `-c`:显示字符数

13. `ps` - 显示当前运行的进程

    - 基本用法:`ps [选项]`

    - 常见选项:

      - `aux`:显示所有进程的详细信息

14. `kill` - 终止正在运行的进程

    - 基本用法:`kill [选项] 进程ID`

    - 常见选项:

      - `-9`:强制终止进程

15. `ifconfig` - 显示和配置网络接口信息

    - 基本用法:`ifconfig [网络接口] [选项]`

    - 常见选项:

      - `-a`:显示所有接口信息

      - `up`:启用网络接口

      - `down`:禁用网络接口

16. `shutdown` - 关闭系统

    - 基本用法:`shutdown [选项] 时间`

    - 常见选项:

      - `-h`:关机

      - `-r`:重启

17. `reboot` - 重新启动系统

    - 基本用法:`reboot`

18. `chmod` - 修改文件权限

    - 基本用法:`chmod [选项] 权限 文件`

    - 常见选项:

      - `+`:添加权限

      - `-`:移除权限

      - `=`:设置权限

    - 示例:

      - `chmod +x script.sh`:赋予`script.sh`可执行权限

      - `chmod 644 file.txt`:设置`file.txt`的权限为644

19. `chown` - 修改文件的所有者

    - 基本用法:`chown [选项] 用户 文件`

    - 常见选项:

      - `-R`:递归修改目录下的文件和子目录的所有者

    - 示例:

      - `chown user1 file.txt`:将`file.txt`的所有者更改为`user1`

      - `chown -R user1 directory/`:递归修改`directory/`下所有文件和子目录的所有者为`user1`

20. `chgrp` - 修改文件的所属组

    - 基本用法:`chgrp [选项] 组 文件`

    - 常见选项:

      - `-R`:递归修改目录下的文件和子目录的所属组

    - 示例:

      - `chgrp group1 file.txt`:将`file.txt`的所属组更改为`group1`

      - `chgrp -R group1 directory/`:递归修改`directory/`下所有文件和子目录的所属组为`group1`

21. `useradd` - 创建新用户

    - 基本用法:`useradd [选项] 用户名`

    - 常见选项:

      - `-m`:同时创建用户的主目录

      - `-G`:指定用户所属的附加组

    - 示例:

      - `useradd john`:创建一个名为`john`的用户

      - `useradd -m -G group1 john`:创建一个名为`john`的用户,并将其加入`group1`组

22. `passwd` - 设置用户密码

    - 基本用法:`passwd [选项] 用户`

    - 常见选项:

      - `-d`:禁用密码(使用户无法登录)

      - `-l`:锁定密码(使用户无法登录)

      - `-u`:解锁密码(允许用户登录)

    - 示例:

      - `passwd john`:为用户`john`设置密码

      - `passwd -d john`:禁用用户`john`的密码

23. `tar` - 打包和解包文件

    - 基本用法:

      - 打包文件:`tar [选项] 目标文件.tar 源文件`

      - 解包文件:`tar [选项] 目标目录 -xf 源文件.tar`

    - 常见选项:

      - `-c`:创建打包文件

      - `-x`:解包文件

      - `-f`:指定源文件名

    - 示例:

      - `tar -cf archive.tar file1 file2`:创建名为`archive.tar`的打包文件,包含`file1`和`file2`

      - `tar -xf archive.tar -C /target/directory`:将`archive.tar`解包到`/target/directory`

24. `gzip` - 压缩文件

    - 基本用法:`gzip [选项] 文件`

    - 常见选项:

      - `-d`:解压缩文件

      - `-r`:递归压缩目录下的所有文件

    - 示例:

      - `gzip file.txt`:压缩`file.txt`,生成`file.txt.gz`

      - `gzip -d file.txt.gz`:解压缩`file.txt.gz`

25. `gunzip` - 解压缩文件

    - 基本用法:`gunzip [选项] 文件`

    - 示例:

      - `gunzip file.txt.gz`:解压缩`file.txt.gz`,生成`file.txt`

Shell脚本

1. Shell脚本是一种用于自动化任务和编写批处理脚本的脚本语言。它们通常在命令行解释器(如Bash)中运行。

2. Shell脚本以`.sh`为文件扩展名,并且需要具有可执行权限才能运行。您可以使用`chmod +x script.sh`命令为脚本添加可执行权限。

3. Shell脚本的第一行通常是`#!/bin/bash`,它指定了要用于解释脚本的Shell解释器。

4. Shell脚本可以包含变量、条件语句、循环、函数等。它们使用简单的语法和命令来完成各种任务。

5. 在Shell脚本中,变量可以通过赋值来创建和访问。例如,`name="John"`定义了一个名为`name`的变量,并将其设置为`John`。

6. 使用`$`符号可以访问变量的值。例如,`echo $name`将打印出变量`name`的值。

7. Shell脚本中的条件语句使用`if-else`结构来执行基于条件的操作。例如:

   ```shell

   if [ $num -gt 10 ]; then

       echo "The number is greater than 10."

   else

       echo "The number is less than or equal to 10."

   fi

   ```

8. 循环结构在Shell脚本中用于重复执行一系列操作。常见的循环有`for`循环和`while`循环。

9. 函数可以在Shell脚本中定义和调用,以便重复使用一段代码。例如:

   ```shell

   greet() {

       echo "Hello, $1!"

   }

   greet "John"

   ```

10. 使用`$1`、`$2`等特殊变量可以访问传递给脚本或函数的参数。例如,在上面的示例中,`$1`表示第一个参数,即`John`。

Linux C系统

1. 理解Linux系统调用:

   - Linux系统调用是与操作系统内核进行交互的接口。它们提供了访问底层系统功能的方法,如文件操作、进程管理、网络通信等。

   - 头文件`<unistd.h>`中包含了许多常用的系统调用函数,如`open()`、`read()`和`write()`等。

2. 文件I/O操作:

   - Linux C编程中文件I/O是一项基本任务。通过使用系统调用函数,可以打开文件、读取文件内容、写入数据以及关闭文件。

   - `open()`函数用于打开文件,`read()`和`write()`函数用于读取和写入文件数据,`close()`函数用于关闭文件。

3. 进程管理:

   - Linux是一个多进程操作系统,允许同时运行多个进程。C语言提供了创建、管理和通信进程的功能。

   - `fork()`函数用于创建一个新进程,`exec()`函数用于在新进程中执行一个程序,`wait()`函数用于等待子进程结束并获取其退出状态。

4. 线程和并发编程:

   - Linux C语言支持线程编程,允许在同一进程中创建多个执行流。线程可以共享进程的资源,提供并发性。

   - `pthread_create()`函数用于创建一个新线程,`pthread_join()`函数用于等待线程结束。

5. 内存管理:

   - 在Linux C编程中,开发者需要手动管理内存分配和释放。

   - `malloc()`和`free()`函数用于动态分配和释放内存,`calloc()`函数用于分配并初始化内存。

6. 网络编程:

   - Linux C语言提供了丰富的网络编程功能,允许开发者创建网络应用程序。

   - `socket()`函数用于创建套接字,`bind()`函数用于将套接字与特定端口关联,`listen()`函数用于侦听连接请求,`accept()`函数用于接受连接。

7. 错误处理:

   - 在Linux C编程中,正确处理错误和异常非常重要。错误处理可确保程序的稳定性和可靠性。

   - 多数系统调用函数返回-1表示错误,此时可以使用`errno`变量获取错误代码。`perror()`函数用于打印错误信息。

8. Makefile和编译:

   - Makefile是一种用于自动化编译和构建程序的脚本。它定义了源文件、依赖关系和编译规则。

   - 使用`gcc`编译器进行编译,可以通过命令行选项指定所需的库和编译标志。

9. 调试和测试:

   - 调试是Linux C编程中的重要环节。`gdb`是一个常用的调试器,用于追踪程序执行和检测错误。

   - 单元测试和集成测试是保证程序质量的关键步骤,可以使用各种测试框架进行测试。

C语言

1. C语言是一种通用的、高效的编程语言,具有简洁而灵活的语法。

 程序由函数组成,每个函数由一系列语句块构成,语句块由花括号括起来。

C语言中的基本数据类型包括整数(int)、字符(char)、浮点数(float、double)和布尔值(bool)等。

变量用于存储数据,在使用变量之前需要声明其数据类型。

C语言支持各种算术、逻辑和关系运算符,用于进行数值计算和条件判断。

表达式是由运算符、操作数和函数调用组成的组合,用于进行计算和生成值。

控制流语句用于根据条件或循环来控制程序的执行流程,包括条件语句(if-else)、循环语句(for、while、do-while)和跳转语句(break、continue、return)等。

数组是一组相同类型的元素的集合,可以通过索引访问和操作数组中的元素。

指针是一个变量,存储一个内存地址,可以用于直接访问和操作内存中的数据。

函数用于将代码模块化,实现代码的可重用性和组织性,函数由函数头和函数体组成。

结构体是一种自定义的数据类型,用于将多个不同类型的数据组合在一起,每个数据称为结构体的成员。

文件操作允许读取和写入文件,可以使用文件指针和文件操作函数来打开、关闭、读取和写入文件。

动态内存分配允许在程序运行时动态地分配和释放内存,可以使用`malloc()`、`calloc()`和`realloc()`等函数进行动态内存分配。

预处理器是C语言编译过程的一部分,用于在实际编译之前对源代码进行处理,宏是预处理器提供的一种机制,允许在程序中定义和使用简单的代码片段。

常见数据结构的总结

1. 数组(Array):

```c

int numbers[5] = {1, 2, 3, 4, 5};

```

数组`numbers`包含了5个整数元素,通过索引可以访问特定位置的元素。例如,`numbers[0]`表示数组的第一个元素,其值为1。

2. 结构体(Structure):

```c

struct Person {

    char name[20];

    int age;

};

struct Person person1;

strcpy(person1.name, "John");

person1.age = 25;

```

定义了一个名为`Person`的结构体,包含了一个字符串类型的`name`成员和一个整数类型的`age`成员。通过结构体,可以创建一个名为`person1`的实例,并为其成员赋值。

3. 链表(Linked List):

```c

struct Node {

    int data;

    struct Node* next;

};

struct Node* head = NULL;

void insertAtBeginning(int value) {

    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));

    newNode->data = value;

    newNode->next = head;

    head = newNode;

}

void displayList() {

    struct Node* current = head;

    while (current != NULL) {

        printf("%d ", current->data);

        current = current->next;

    }

}

```

上述代码展示了使用链表实现头插法插入元素和显示链表的操作。首先,定义了一个名为`Node`的结构体,包含一个整数类型的`data`成员和一个指向下一个节点的指针`next`。然后,通过`insertAtBeginning`函数在链表头部插入新节点。最后,通过`displayList`函数遍历链表并打印节点的值。

4. 栈(Stack):

```c

#define MAX_SIZE 100

int stack[MAX_SIZE];

int top = -1;

void push(int value) {

    if (top >= MAX_SIZE - 1) {

        printf("Stack Overflow\n");

        return;

    }

    stack[++top] = value;

}

int pop() {

    if (top == -1) {

        printf("Stack Underflow\n");

        return -1;

    }

    return stack[top--];

}

```

以上代码演示了使用数组实现栈的`push`(入栈)和`pop`(出栈)操作。栈的最大容量由常量`MAX_SIZE`定义,栈顶索引为`top`。通过`push`函数将元素压入栈中,通过`pop`函数从栈中弹出元素。

5. 队列(Queue):

```c

#define MAX_SIZE 100

int queue[MAX_SIZE];

int front = 0;

int rear = -1;

void enqueue(int value) {

    if (rear >= MAX_SIZE - 1) {

        printf("Queue Overflow\n");

        return;

    }

    queue[++rear] = value;

}

int dequeue() {

    if (front > rear) {

        printf("Queue Underflow\n");

        return -1;

    }

    return queue[front++];

}

```

上述代码展示了使用数组实现队列的`enqueue`(入队)和`dequeue`(出队)操作。队列的最大容量由常量`MAX_SIZE`定义,队列的前端和后端分别由变量`front`和`rear`表示。通过`enqueue`函数将元素插入队列尾部,通过`dequeue`函数从队列头部移除元素。

树(Tree):

```c

struct TreeNode {

    int data;

    struct TreeNode* left;

    struct TreeNode* right;

};

struct TreeNode* createNode(int value) {

    struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));

    newNode->data = value;

    newNode->left = NULL;

    newNode->right = NULL;

    return newNode;

}

void insert(struct TreeNode** root, int value) {

    if (*root == NULL) {

        *root = createNode(value);

        return;

    }

    if (value < (*root)->data) {

        insert(&((*root)->left), value);

    } else {

        insert(&((*root)->right), value);

    }

}

void inorderTraversal(struct TreeNode* root) {

    if (root != NULL) {

        inorderTraversal(root->left);

        printf("%d ", root->data);

        inorderTraversal(root->right);

    }

}

```

上述代码展示了使用结构体和指针实现二叉搜索树(Binary Search Tree)的插入和中序遍历操作。首先,定义了一个名为`TreeNode`的结构体,包含一个整数类型的`data`成员和指向左子树和右子树的指针。然后,通过`createNode`函数创建新节点,并通过`insert`函数将节点插入二叉搜索树。最后,通过`inorderTraversal`函数进行中序遍历,按升序打印树中的节点值。

图(Graph):

```c

#define MAX_VERTICES 100

struct Graph {

    int numVertices;

    int adjacencyMatrix[MAX_VERTICES][MAX_VERTICES];

};

void initGraph(struct Graph* graph, int numVertices) {

    graph->numVertices = numVertices;

    int i, j;

    for (i = 0; i < numVertices; i++) {

        for (j = 0; j < numVertices; j++) {

            graph->adjacencyMatrix[i][j] = 0;

        }

    }

}

void addEdge(struct Graph* graph, int src, int dest) {

    if (src >= 0 && src < graph->numVertices && dest >= 0 && dest < graph->numVertices) {

        graph->adjacencyMatrix[src][dest] = 1;

        graph->adjacencyMatrix[dest][src] = 1;

    }

}

void printGraph(struct Graph* graph) {

    int i, j;

    for (i = 0; i < graph->numVertices; i++) {

        for (j = 0; j < graph->numVertices; j++) {

            printf("%d ", graph->adjacencyMatrix[i][j]);

        }

        printf("\n");

    }

}

```

以上代码展示了使用邻接矩阵(Adjacency Matrix)实现图的创建、添加边和打印图的操作。首先,定义了一个名为`Graph`的结构体,包含一个整数类型的`numVertices`成员和二维数组`adjacencyMatrix`用于存储图的邻接关系。然后,通过`initGraph`函数初始化图的顶点数量和邻接矩阵。通过`addEdge`函数添加边,将对应位置的邻接矩阵元素设为1表示顶点之间存在边。最后,通过`printGraph`函数打印邻接矩阵,展示图的结构。

学习Linux I/O

1. 标准输入/输出/错误(stdin/stdout/stderr):

   - 标准输入(stdin)是程序默认从中读取数据的流。通常情况下,它连接到键盘。

   - 标准输出(stdout)是程序默认将数据写入的流。通常情况下,它连接到终端或控制台。

   - 标准错误输出(stderr)用于将错误和诊断信息发送到终端或控制台。

2. 文件描述符的使用:

   - 文件描述符是非负整数,用于标识打开的文件或其他I/O资源。

   - 使用系统调用`open`打开文件时,会返回一个新的文件描述符。

   - 标准输入、输出和错误输出的文件描述符分别为0、1和2。

3. 文件打开模式:

   - 打开文件时,可以指定打开模式。常见的打开模式包括读取(O_RDONLY)、写入(O_WRONLY)、追加(O_APPEND)等。

   - 可以通过逻辑或(|)操作符将多个模式组合在一起,例如读写模式(O_RDWR)。

4. 文件操作函数:

   - `open`:打开文件并返回文件描述符。

   - `close`:关闭文件。

   - `read`:从文件中读取数据。

   - `write`:将数据写入文件。

   - `lseek`:在文件中进行定位。

   - `fcntl`:用于对文件描述符进行各种操作,例如修改文件状态标志。

5. 错误处理:

   - 文件操作函数在发生错误时会返回-1或其他特殊值。

   - 可以使用全局变量`errno`获取具体的错误代码。

   - 可以使用`perror`函数将错误信息打印到标准错误输出(stderr)。

6. 文件和目录的创建、删除和重命名:

   - `mkdir`:创建目录。

   - `rmdir`:删除目录。

   - `unlink`:删除文件。

   - `rename`:重命名文件或目录。

7. 文件权限和属性:

   - 使用`chmod`可以修改文件的权限。

   - 使用`chown`可以修改文件的所有者和所属组。

   - 使用`stat`可以获取文件的详细属性信息,如大小、权限、时间戳等。

8. 缓冲I/O和直接I/O:

   - 缓冲I/O使用缓冲区进行读写操作,常见的缓冲函数包括`fread`和`fwrite`。

   - 直接I/O绕过操作系统的缓冲区,直接读写磁盘,常见的直接I/O函数包括`read`和`write`。

Linux中进程和线程

1. 进程和线程的基本概念:

   - 进程是操作系统对正在运行的程序的抽象。它包括程序的代码、数据和资源的实例。

   - 线程是进程内的执行单元。一个进程可以包含多个线程,它们共享进程的地址空间和资源,但具有独立的栈空间和线程上下文。

2. 进程的创建和终止:

   - 使用系统调用`fork`可以创建一个新的子进程。子进程是父进程的副本,从调用`fork`的位置开始执行。

   - 子进程有自己独立的进程标识符(PID),但继承了父进程的打开文件描述符、信号处理程序和部分内存内容。

   - 父进程可以使用`wait`或`waitpid`等系统调用等待子进程的终止,并获取子进程的退出状态。

3. 进程间通信(IPC):

   - 进程可以使用多种机制进行通信,如管道、共享内存、消息队列和信号量。

   - 管道是一个单向的字节流,可用于父子进程或具有共同祖先的进程之间的通信。

   - 共享内存允许多个进程访问相同的内存区域,从而实现高效的数据共享。

   - 消息队列允许进程通过发送和接收消息来进行通信。

   - 信号量用于同步进程和提供互斥访问共享资源。

4. 线程的创建和终止:

   - 使用系统调用`pthread_create`可以在进程中创建一个新的线程。

   - 线程共享进程的虚拟地址空间、文件描述符和其他资源。

   - 线程可以通过调用`pthread_join`等待其他线程的终止,并获取其返回值。

5. 线程同步与互斥:

   - 多个线程同时访问共享资源可能导致数据竞争和不一致的问题。

   - 互斥量(Mutex)用于确保在给定时间只有一个线程可以访问共享资源。线程可以使用`pthread_mutex_lock`和`pthread_mutex_unlock`来获取和释放互斥量。

   - 条件变量(Condition Variable)用于线程之间的等待和通知机制。线程可以使用`pthread_cond_wait`等待条件变量,而其他线程可以使用`pthread_cond_signal`或`pthread_cond_broadcast`通知等待的线程。

6. 线程的调度和优先级:

   - 线程调度器决定在给定时间片内运行哪个线程。

   - Linux提供了不同的调度策略,如实时调度策略(SCHED_FIFO和SCHED_RR)和普通时间共享调度策略(SCHED_OTHER)。

   - 可以使用`pthread_setschedparam`设置线程的调度参数和优先级。

7. 线程的并发编程:

   - 并发编程涉及多个线程同时执行,因此需要考虑同步和互斥问题。

   - 正确使用互斥量、条件变量和原子操作可以避免竞态条件和数据不一致性。

   - 并发编程还需要处理死锁、活锁和饥饿等问题,使用适当的算法和技术来避免这些情况的发生。

8. 进程和线程的调试和监控:

   - Linux提供了多种工具和命令来调试和监控进程和线程的行为。

   - `gdb`是一个功能强大的调试器,可用于追踪进程和线程的执行、设置断点和检查变量的值。

   - `strace`是一个系统调用跟踪工具,可以用于监视进程的系统调用和信号。

   - `top`命令可以实时显示系统中运行的进程和线程的状态和资源使用情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值