介绍man命令
在Linux中,man命令用于查看系统手册页(manual pages)。系统手册页是关于各种Linux命令、函数库以及系统调用的详尽文档,能够提供关于命令的使用方法、参数说明、示例以及其他相关信息
可以利用man xxx的命令去查找某个函数某个命令的用法
inode
每一个文件都有一个索引节点inode,inode 是由文件系统提供的唯一数值编址,这个数
值称为inode 编号。索引节点是唯一的,同一个系统下,每一个索引节点对应一个文件(目录
也可以当做文件),可以把inode理解成身份证号。
可以用“ls -i”去查看索引节点
man去查询测试mkdir文件
先在终端输入命令“man 2 mkdir”,之后下拉找到
再往下的SEE ALSO会介绍相关的函数
测试代码
#include<stdio.h>//mkdir函数头文件
#include<sys/stat.h>
#include<sys/types.h>
int main(int argc,char *argv[]){
int ret;
//检测参数
if(argc <2)
{printf("\n Please input file path\n");return 1;}
//使用mkdir函数新建目录
ret = mkdir(argv[1],0777);
if(ret<0)
{printf("mkdir %s failed!\n",argv[1]);return 1;}
printf("mkdir %s suceces!\n",argv[1]);
return 0;}
代码分析:
main里的参数: argc
是命令行参数的数量,argv
是一个指向参数字符串数组的指针
if语句检查命令行参数的数量,如果少于 2 个(即没有输入文件路径),则打印提示信息并返回 1,表示程序运行出错
【注释:命令行参数的数量是指在运行程序时通过命令行输入的参数的个数,其中第一个参数通常是程序的名称(例如 ./myprogram
),后续的参数可以是用户自定义的,所以按理我们应该会输入文件路径,加上原有的文件名称,应该是有两个命令行参数】
argv[1]
是第二个命令行参数,即用户输入的文件路径
之后可以用U盘拷贝到开发板的方法去运行这个测试程序
使用man 学习link 函数
在Linux系统中,硬链接是一种特殊的文件链接方式,它允许一个文件拥有多个不同的文件名,但实际上它们都指向同一个inode,比如目录1和2的索引节点是一样的,这两个其实都是指向同一个文件,就像一个人有学号和名字一样,指的都是同一个人,这种情况就是属于linux 文件中的硬链接。
和硬链接对应的是软链接,也可以叫符号链接或者symlinks,软连接不是文件系统的文件
名和inode 的映射,而是一种指针。换句话说,符号链接就像是一个快捷方式,它指向另一个文件或目录
link函数:
使用命令“man 2 link”,之后有
int link(const char *oldpath, const char *newpath);
参数*oldpath:已有的文件路径。
参数*newpath:新建的硬链接文件路径。
#include<studio.h>
#include<unisted.h>
int main(int argc,char *argv[]){
int ret;
if(argc <3)
{
printf("\nPlease input file path\n");
return 1;
}
//测试1ink函数
ret = link(argv[1l,argv[2]);
if(ret){
printf("link failed");
return 1;}
printf("link %s to %s success!\n",argv[1],argv[2]);
return 0;}
编译程序为可执行程序后,将文件拷至U盘,后在开发板上运行,则可见
之后用ls -i可见linktest和linktest.c文件的inode是一样的
Linux里的进程
大家几乎都是先学单片机再来学Linux的,在单片机里,我们知道其实主要是对一些寄存器进行控制,比如在某个寄存器里写入1就可以实现中断等等。而Linux是一种操作系统,和裸机对比起来,操作系统有更多的软件资源,可以调用函数去实现多任务运行,而不是像单片机一样去用中断实现一些操作。
先理解程序,何为程序,就是我们上面的那些例程,如果程序比较大,就可以称为应用
很多人不是很清楚线程,进程和程序的区别:
进程是正在执行的程序,可以把线程理解成轻量级的进程(记住“轻量级”这个特点),而且进程是分配资源的最小单位,属于同一个进程的线程由于没有被单独分配资源,所以它们都是共享进程的资源的(如地址空间等),但是每个线程会拥有独属于自己的栈
在Linux系统里可以通过“top”命令去查看在运行的线程(类似于Windows的任务管理器)
进程id
在n时刻,每个进程都有一个唯一的id,比如进程A在n时刻的id是100(但是假如在n+s时刻,可能会有进程B的进程也是100的情况),进程的id在固定的时刻是唯一的。
进程ID通常是一个正整数值,范围可以根据操作系统的不同而有所不同。在大多数系统中,进程ID从1开始递增,直到达到最大值后再从1重新开始分配(分配的都是已死的进程)。
进程ID为1的进程通常是init进程,它是系统启动时由内核创建的,是第一个用户级进程。除了init 进程,其它进程都是由其它进程创立的。创立新进程的进程叫父进程,新进程叫子进程。
使用命令“man 2 getpid”
橙色部分说明了这两函数:
getpid是获取进程号的 getppid是获取父进程号的’
我们编写测试程序,可以直接定义pid_t id1/id2,之后就直接调用getpid函数和getppid函数
然后可以将测试文件编译成可执行文件,到开发板执行后可以看见进程和其父进程的id
exec 函数族
exec函数族允许我们将当前进程替换为另一个进程,并且新进程可以继承原进程的一些资源
函数族包括
这些exec函数族中的函数实际上是用于在当前进程中执行一个新的程序,当调用这些函数时,当前进程的内容会被替换为新程序的内容,但进程的标识(如进程ID)以及其它一些属性(如进程的父子关系)通常会被保留
fork函数
fork函数会将原始进程(称为父进程)完全复制一份,包括代码、数据、堆栈等。然后,这个复制的进程就成为了新的子进程。父进程和子进程是两个独立的进程,它们各自有自己的内存空间和执行流程
在fork函数调用完成后,会返回两次。对于父进程,fork函数的返回值是子进程的进程ID,而对于子进程,fork函数的返回值是0。这样,通过检查返回值,我们可以确定当前代码正在哪个进程中执行,从而采取不同的操作
#include <stdio.h>
#include <unistd.h>int main() {pid_t pid; // 进程IDint n = 100; // 初始值pid = fork(); // 创建一个新进程if (pid == -1) { // 如果出错printf("Error: Failed to create child process.\n");return 1;}else if (pid == 0) { // 子进程printf("Child process: PID=%d, n=%d\n", getpid(), ++n); // 修改n值,并输出}else { // 父进程printf("Parent process: PID=%d, n=%d\n", getpid(), n); // 输出n值}return 0;
}
会输出
Child process: PID=2678, n=101
Parent process: PID=2677, n=100
n的值其实暗示了我们刚刚所说的“父进程和子进程是两个独立的进程,它们各自有自己的内存空间和执行流程”,子进程修改自己n的值是不会影响父进程的
进程终止exit:
当调用exit函数时,当前进程将会立即终止,并返回操作系统。同时,exit函数还会将终止状态传递给操作系统,供父进程获取
#include <stdio.h>
#include <stdlib.h>int main() {printf("This is before the exit function\n");exit(0);printf("This is after the exit function\n"); // 这行代码不会执行return 0;
}
最后输出“This is before the exit function”
总之,exit函数可以立即终止当前进程,并传递一个状态值给操作系统,用于标识进程的终止状态