LOADING

加载过慢请开启缓存 浏览器默认开启

zero two

mit-6s081-lab02-System_call_tracing

操作系统 2025/5/19

声明

文章仅具有解释意义
希望能为你搭建知识框架

过程

Makefile Modification:

makefile
UPROGS=

$U/_trace
User Space Modifications:

user/user.h:

int trace(int);

user/usys.pl:

entry("trace");

Kernel Modifications:

kernel/syscall.h:

#define SYS_trace 22

kernel/syscall.c:


extern uint64 sys_trace(void);
//这里是自己添加不是将syscalls修改
static char *syscall_names[] = {   
    [SYS_fork]    "fork",
    [SYS_exit]    "exit",
    [SYS_wait]    "wait",
    [SYS_pipe]    "pipe",
    [SYS_read]    "read",
    [SYS_kill]    "kill",
    [SYS_exec]    "exec",
    [SYS_fstat]   "fstat",
    [SYS_chdir]   "chdir",
    [SYS_dup]     "dup",
    [SYS_getpid]  "getpid",
    [SYS_sbrk]    "sbrk",
    [SYS_sleep]   "sleep",
    [SYS_uptime]  "uptime",
    [SYS_open]    "open",
    [SYS_write]   "write",
    [SYS_mknod]   "mknod",
    [SYS_unlink]  "unlink",
    [SYS_link]    "link",
    [SYS_mkdir]   "mkdir",
    [SYS_close]   "close",
    [SYS_trace]   "trace",
};

kernel/sysproc.c:

uint64 sys_trace(void) {
    int mask;
    if (argint(0, &mask) < 0)
        return -1;
    struct proc *p = myproc();
    p->trace_mask = mask;
    return 0;
}

kernel/proc.h:

struct proc {
    ...
    int trace_mask;
    ...
};

kernel/proc.c (fork and allocproc):

int fork(void) {
    ...
    np->trace_mask = p->trace_mask;
    ...
}

static struct proc* allocproc(void) {
    ...
    p->trace_mask = 0;
    ...
}
kernel/syscall.c (syscall function):
void syscall(void) {
    int num;
    struct proc *p = myproc();

    num = p->trapframe->a7;
    if (num > 0 && num < NELEM(syscalls) && syscalls[num]) {
        p->trapframe->a0 = syscalls[num]();
        if ((p->trace_mask & (1 << num)) != 0) {
            char *name = "unknown";
            if (num < NELEM(syscall_names) && syscall_names[num] != 0) {
                name = syscall_names[num];
            }
            printf("%d: syscall %s -> %d\n", p->pid, name, p->trapframe->a0);
        }
    } else {
        printf("%d %s: unknown sys call %d\n", p->pid, p->name, num);
        p->trapframe->a0 = -1;
    }
}
阅读全文

关于wsl无法使用samba

linux 2025/5/17

问题:
WSL 默认不支持直接运行 smbd
原因:
smbd 需要访问低层网络功能(如绑定到端口 445),WSL2 虚拟环境不允许这样做。
WSL2 的网络和 Windows 是隔离的(类似虚拟机),而且端口 445 通常已被 Windows 自身的 SMB 服务占用,smbd 无法监听。
推荐解决方案:
用 Windows 的 SMB 服务共享 WSL 文件夹
方法:

  1. wsl -l -v
    输出:
    NAME      STATE           VERSION  
    Ubuntu    Running         2  
    
    记住这个 name
  2. 在资源管理器地址栏输入 \\wsl$\name\home\share/home/share 是共享的文件夹,自行寻找)
    此时可以验证在 WSL 里共享文件夹下创建一个文件,在 Windows 查看是否存在
阅读全文

mit-6s081-lab01-xargs

操作系统 2025/5/15

前置知识

exec

exec命令的基本语法
exec命令的基本语法如下:

exec [options] [command] [arguments]

options: 可选参数,用于修改exec的行为。
command: 要执行的可执行文件或命令。
arguments: 传递给command的参数。
如果没有指定command,exec将用于修改当前shell的环境变量、文件描述符等设置。


read/write 参数012

fd:文件描述符,表示将数据写入到哪里。可以是文件、设备、套接字等。文件描述符是一个整数,通常是由 open 系统调用返回的。

0:标准输入(stdin)
1:标准输出(stdout)
2:标准错误(stderr)

sh < xxx.sh

sh < xargstest.sh 是在 xv6 实验环境中用于测试 xargs 实现的指令,其核心作用是通过输入重定向将脚本内容传递给 sh 解释器执行
等效于 cat xargstest.sh | sh,但更高效(避免中间管道进程)
.sh里面可能是一些命令然后重定向给sh执行

代码

#include "kernel/types.h"
#include "user/user.h"
#include "kernel/param.h"

#define MAXLINE 1024

void parse_args(char *line, char **args, int *argc) {
    *argc = 0;
    while (1) {
        // 跳过前导空格
        while (*line == ' ') {
            line++;
        }
        if (*line == '\0') {
            break;
        }
        args[(*argc)++] = line;
        // 寻找参数的结尾
        while (*line != ' ' && *line != '\0') {
            line++;
        }
        // 分割参数
        if (*line == ' ') {
            *line = '\0';
            line++;
        }
        if (*argc >= MAXARG) {
            break;
        }
    }
}

int read_line(int fd, char *buf, int max, int *found_newline) {
    int i = 0;
    *found_newline = 0;
    while (i < max - 1) {
        char ch;
        int n = read(fd, &ch, 1);
        if (n < 0) {
            return -1;
        }
        if (n == 0) {
            break; // EOF
        }
        if (ch == '\n') {
            *found_newline = 1;
            break;
        }
        buf[i++] = ch;
    }
    buf[i] = '\0';
    return i;
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        char *msg = "xargs: missing command\n";
        write(2, msg, strlen(msg));
        exit(1);
    }

    while (1) {
        char line[MAXLINE];
        int found_newline;
        int len = read_line(0, line, sizeof(line), &found_newline);
        if (len < 0) {
            char *msg = "xargs: read error\n";
            write(2, msg, strlen(msg));
            exit(1);
        }
        if (len == 0 && !found_newline) {
            break; // EOF
        }

        char *args[MAXARG];
        int new_argc = 0;
        parse_args(line, args, &new_argc);

        char *new_argv[MAXARG];
        int total_args = 0;

        // 添加命令名称
        new_argv[total_args++] = argv[1];

        // 添加原参数
        for (int i = 2; i < argc; i++) {
            if (total_args >= MAXARG) {
                char *msg = "xargs: too many arguments\n";
                write(2, msg, strlen(msg));
                exit(1);
            }
            new_argv[total_args++] = argv[i];
        }

        // 添加新参数
        for (int i = 0; i < new_argc; i++) {
            if (total_args >= MAXARG) {
                char *msg = "xargs: too many arguments\n";
                write(2, msg, strlen(msg));
                exit(1);
            }
            new_argv[total_args++] = args[i];
        }

        new_argv[total_args] = 0; // 参数数组以NULL结尾

        // 创建子进程执行命令
        int pid = fork();
        if (pid < 0) {
            char *msg = "xargs: fork failed\n";
            write(2, msg, strlen(msg));
            exit(1);
        } else if (pid == 0) {
            // 子进程执行命令
            exec(new_argv[0], new_argv);
            // 如果exec失败
            char *msg = "xargs: exec failed\n";
            write(2, msg, strlen(msg));
            exit(1);
        } else {
            // 父进程等待子进程完成
            wait(0);
        }
    }

    exit(0);
}

一些解释

以echo hello too | xargs echo bye为例
首先会执行echo hello too输出到终端缓冲区,通过管道符传递给xargs的标准输入0
然后xargs运行时参数为char *argv[]={‘xargs’,‘echo’,‘bye’}
read_line会读取标准输入里的数据也就是hello too到line字符数组
parse_args解析line存到args指针数组里
此时args里就是{“hello\0”,“too\0”}
构造一个新的命令new_argv
这个新命令的索引:
0:echo
1:bye
添加args
2:hello
3:too
4:0
最后exec执行输出bye hello too,中间的空格应该是自己识别的吧

整理一下AI的总结

在Linux系统中,管道符|通过以下机制将数据从左侧命令传递给右侧命令,具体流程如下:
一、管道符的底层实现原理
匿名管道创建
当用户执行cmd1 | cmd2时,Shell会调用pipe()系统调用创建一个匿名管道(Anonymous Pipe),该管道由两个文件描述符(read_fd和write_fd)表示。
进程间文件描述符重定向
Shell通过fork()创建两个子进程(分别执行cmd1和cmd2),并利用dup2()将文件描述符重定向:
cmd1的标准输出(文件描述符1)被重定向到管道的write_fd,其输出不再直接发送到终端,而是写入管道。
cmd2的标准输入(文件描述符0)被重定向到管道的read_fd,其输入源变为管道。
内核缓冲区的数据传输
左侧命令(cmd1)的输出数据首先写入内核空间的管道缓冲区(默认4KB),而非直接发送到屏幕。
右侧命令(cmd2)通过read()系统调用从管道缓冲区按需读取数据,若缓冲区为空则阻塞等待。

管道是单向通信,数据从echo的stdout流向cat的stdin。

存储位置:当直接执行echo hello时,字符串hello默认通过标准输出(文件描述符1)发送到终端屏幕(即字符设备文件,如/dev/tty) echo内部应该有一个print 从0转变为1

阅读全文

虚拟机Linux超级块不匹配/启动提示无法在分区之外空间读取和写入

Linux 2025/5/14
注意

过程我有些记不清了,可以先看链接处理,主要是后面要进入parted模式
第一次no然后后面的就是yes那里不出意外很快的,我有一次按了很久的y都没成功,虽然不知道有没有影响
然后操作里会有选择start、end就将大小改回来就可以了
下面不保证操作顺序的正确
可以问问ai那些命令是什么意思判断调整顺序

“Either the superblock or the partition table is likely to be corrupt!” after partition resized

  1. 首先下载与你损坏虚拟机版本相同的iso文件,将损坏虚拟机的cd改为该iso,启动后try … install进入,即可使用命令行操作

  2. sudo fdisk -l /dev/whatever 比如/dev/sda(还是sda2了)
    
  3. 将结果抄在纸上。然后修复分区表:

    sudo fdisk /dev/whatever
    
  4. sudo fdisk /dev/sdX  # 替换为你的磁盘设备,如 /dev/sda
    
阅读全文

mit_6s081_lab01_find

操作系统 2025/5/13
知识点:
  1. stat 命令用于显示文件或文件系统状态的详细信息。它提供了比 ls -l 更加详细的输出,包括时间戳、权限、所有者等信息。用法:stat [选项]… 文件…
    显示文件或文件系统的状态。

  1. ‌dirent‌是C语言中用于文件操作的一个头文件,主要提供目录遍历功能,适用于需要访问文件系统的程序。在Linux等Unix-like系统中,它是标准库的一部分,但在Windows系统中需要使用其他API。dirent通过struct dirent结构体和一系列函数,如opendir(), readdir(), 和closedir()等,提供了基本的目录操作接口。

    dirent结构体
    dirent结构体用于描述目录中的条目,主要成员包括:

    ‌d_ino‌:文件的inode号码。
    ‌d_reclen‌:目录项的长度(以字节为单位)。
    ‌d_namlen‌:目录项名称的长度(不包括终止null字符)。
    ‌d_name‌:目录项的名称(以null结尾的字符串)。主要函数
    ‌opendir()‌:打开一个目录流,返回一个指向DIR结构的指针。如果无法打开目录,返回NULL。
    ‌readdir()‌:从目录流中读取下一个目录项,返回一个指向dirent结构体的指针。如果目录流中没有更多目录项,返回NULL。
    ‌closedir()‌:关闭一个目录流,释放与该目录流关联的系统资源。
    ‌rewinddir()‌:将目录流重置到开头。
    ‌seekdir()‌:将目录流移动到指定位置。
    ‌telldir()‌:返回目录流的当前位置。

阅读全文

mit_6s081_lab01_primes

操作系统 2025/5/12

这是关于mit6.s081课程中的lab01中primes实现的记录

阅读全文

Hello World

2023/11/5

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

$ hexo new "My New Post"

More info: Writing

Run server

$ hexo server

More info: Server

Generate static files

$ hexo generate

More info: Generating

Deploy to remote sites

$ hexo deploy

More info: Deployment

阅读全文
1 ... 3
avatar
lAn_rEd

Description
山的背面是未知,天空没有尽头

问答