Linux学习笔记1

  • linux系统的目录是一个倒状树

顶层 根目录 /

bin 命令

boot 系统内核以及系统启动的文件

dev 系统硬件设备

etc 系统配置文件

lib 系统库

proc 系统内存的信息 (虚拟 内存在磁盘上的映射)

usr 不常改变的程序

var 经常改变的(日志/邮件...)


  • 基本操作

cd + 位置 可以跳转

cd .. 退到上一层

ctrl+l 或者 clear 清屏

ls -l 看文件类型

普通文件 -

管道文件 p


  • 命令:

文件: mv 移动 cp 拷贝 rm删除 touch 创建普通文件 mkdir 创建文件夹 cat查看文件 more less head tail vi/vim find 查找文件 grep 过滤

进程: ps 查看进程 kill 结束进程 & 将进程放入后台执行

  • gcc gdb 静态库 共享库

两个库在使用上的区别: 静态库 每一个用户在使用是都需要加载进自己的程序 共享库则直接调用即可

  • printf 缓冲区内容被输出到屏幕三种方法:1 缓冲区放满 2 缓冲区未满 强制刷新 3 程序结束

程序执行结果会存放在缓冲区 当进程结束后 缓冲区数据展现出来,\n会强制刷新缓冲区

exit(0) 1. 刷新缓冲区2. 退出进程 调用_exit()

刷新缓冲区另一种方法 fflush(stdout) // stdin/stdout 屏幕标准输入/输出 stderr 标准错误输出 (类型FIFE*)

  • main 参数

  • fork 复制进程

linux vim中结束语句一般是exit(0); (头文件#include<stdlib.h>)

0代表成功 1代表失败

gcc -o 生成文件名 运行文件名

./生成文件名

echo 打印

pwd 显示工作路径


  • main函数参数有三(int参数个数argc; char*参数内容argv[]; char*环境变量envp[])

可以从主函数 拿到用户传入的参数

echo $PATH // $ 打印PATH的值

echo PATH // 不加$打印PATH

int main(int argc, char* argv[], char* envp[])
{
    printf("argc=%d\n",argc);
    int i = 0;
    for(; i < argc; i++)
    {
        printf("argv[%d] = %s\n", i, argc[i]);
    }
    for(i = 0; envp[i] != NULL; i++)
    {
        printf("envp[%d] = %s\n", i, envp[i]);
    }
    exit(0);
}

计算机抽象图

手机存储6 + 128 (6 内存大小 128 硬盘大小)

main.c and main程序都存放在硬盘中,执行./main时通过I/O设备传入内存

内存重点数据在断电后就没有了

程序: 由一条条指令组成 (菜谱)

程序运行时产生进程 (厨房)

进程执行一条条指令

操作系统:管理计算机上软硬件资源 (管理内存 进程 文件)

为什么main.c程序需要编译成main.exe/main可执行文件 才可以执行呢?

计算机只可以执行二进制的指令(0101) 这样的指令集合称之为指令系统

linux上可执行文件格式

ELE

windows上可执行文件格式

PE


进程

进程控制块PCB 用结构体实现的 链表 每个链表节点中存放进程信息

操作系统中 进程控制块是进程存在的唯一信息

struct task_struct;
{
    int pid; // 进程id
    int status; //进程状态
    ...
}

linux的内核-C语言 1991 芬兰学生第一个版本

进程基础三状态 : 就绪 运行 阻塞

就绪

其他信息都准备好了,等待处理器调动

运行

CPU处理器开始执行

阻塞

某个信息没有准备好,不能执行

进程三状态

并发&并行

单位时间内交替执行 并发

两个处理器同时运行 并行

并行 并发

内存管理

页表记录 逻辑页(程序)与物理页(内存)的关系 操作系统管理空闲的物理页,将逻辑页分配过去

32位 全零到全一 4G

进程地址空间

  • fork() 复制一个进程 父进程的fork返回值是子进程的id号 子进程中fork返回值是0

父进程的内存 -> 复制给子进程 (写时拷贝) , 父进程中fork后 子进程会从该fork后开始执行,fork前会复制过来

复制出来的子进程从pid_t pid = fork() 开始执行(将前面的运行结果对其也有影响) eg. 父进程开始n=0 那么子进程中的n也为0

父进程的父进程是bash,在终端中执行的命令时会先把bash复制一份

写时拷贝 : 为了提高fork效率,父子进程的内存页面改了就复制,没改就共享

  • 父子进程 物理内存上n是否是同一个空间?? 不在

原因1 &n打印的是逻辑地址(偏移量) 不是真实的地址

原因2 fork后会复制父进程同样大小的空间给子进程

[有了逻辑地址和页表(在proc中存着)就可以计算出物理地址]

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/types.h>

int main(int argc, char* argv[], char*envp[])
{
    int n = 0; // 定义一会要打印数据的个数
    char * s = NULL; // 记录父子进程要打印的内容
    pid_t pid = fork(); // err -1 运行到此 会复制出一个子进程 子进程会从此继续执行 父进程pid为子进程的进程号 子进程的pid为0
    if(pid == -1)
    {
        exit(1);
    }
    if(pid == 0)
    {
        n = 3;
        s = "child";
    }
    else
    {
        n = 7;
        s = "parent";
    }
    for(int i = 0; i < n; i++)
    {
        
        printf("s = %s, curr_pid = %d, curr_ppid = %d, &n = %p, n = %d \n", s, getpid(), getppid(), &n, n); // pid 当前进程的id号 ppid是当前进程的父id号
        
        sleep(1);
    }
    exit(0);
}
  • 僵死进程:子进程先结束,父进程没有wait获取子进程的退出码

解决办法: 1.父进程wait, wait可以使子进程不成为僵死进程

2. 父进程先结束,直接退出,子进程变成孤儿进程,孤儿进程由init进程(或其他进程)接管,由init进程执行wait

进程控制(wait 和 waitpid)的理解和使用https://blog.csdn.net/m0_46606290/article/details/123609793

./fork & (后台执行)


面试题

输出多少个A??? 三个

  • 逻辑或 A || B 三种可能

1 A为false(假),继续B判断,如果也为false(假),结果为false(假)

2 A为false(假),继续B判断,如果为true(真),结果为true(真)

3 A为true(真),则不再进行B判断,结果为true(真)

输出多少A??? 6个

输出多少A??? 8个

输出两个A 原因:父进程的缓冲区有一个A,fork后 子进程将父进程的缓冲区也复制过来其中包含A,子进程结束后会将缓冲区内容输出 ,所以是两个A.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值