Magenta - Namespace

本文介绍了Magenta操作系统中Namespace的实现原理及其与文件系统的关联。通过客户端和服务端的交互方式,文章详细展示了如何通过namespace-test程序来创建文件和目录的映射,以及如何解决因库文件缺失而导致的应用程序执行失败的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Magenta - Namespace


Magenta的Namespace当前比较简单,只实现了类似于Linux的Mount-space,其他的space隔离暂未看到。Namespace的实现和其文件系统密切相关,后续有机会详细描述,现在只大概说明。

Magenta是以Client/Service的方式实现了文件系统。在devmgr进程中,除了做设备管理之外(device add,device remove, etc),还有1个线程mxio-dispatcher作为文件操作service(open,close,read,write, etc)。其他进程在打开文件时,会通过channel将request发送给service,service执行完文件操作后,将结果返回。

可见在上述的文件架构上,还是很容易实现mount-space的。即本地先创建一个虚拟的文件目录,并将本地的文件映射到service可见的对应的文件即可。


在目前Magenta有个测试程序namespace-test,我们可以实际跑起来看看效果。namespace-test运行时可带参数或不带参数。

当不带参数时,创建如下的映射:

{ "/bin", "/boot/bin" },
{ "/lib", "/boot/lib" },
{ "/fake", "/boot" },
{ "/fake/dev", "/dev" },
{ "/fake/tmp", "/tmp" },
{ "/fake/dev/class/pci/xyz", "/boot/src" },

前者是本地的虚拟文件或目录,后者是root目录下的文件或目录。运行以后,枚举前者目录下的文件,会发现和后者下的文件一样。

我们重点看看带参数运行的情况。

$ namespace-test /bin=/boot/bin
{ .handle = 0x6ce666a3, type = 0x00000020, .path = '/bin' },

在本地只创建1个目录/bin,对应到目录/boot/bin。

$ ls /
d  1        0 bin

可见当前根目录下只有1个目录。

$ ps
/boot/bin/sh: 2: ps: not found
$ echo $PATH
/system/apps:/system/bin:/boot/bin

执行ps失败,是因为/bin目录默认不在PATH路径中,所以未搜索到命令ps。

$ PATH=/system/apps:/system/bin:/boot/bin:/bin
$ ps
dlsvc: could not open 'ld.so.1'
/boot/bin/sh: 5: Cannot create child process: (UNKNOWN): elf_load: handle_interp failed

将/bin目录添加进PATH路径中,可以搜索到ps,但执行失败,因为我们没有映射lib库,导致搜索不到ld.so.1。

我们重新执行namespace-test,将目录/boot/lib也映射。

$ namespace-test /bin=/boot/bin /boot/lib=/boot/lib 
{ .handle = 0x36307b6d, type = 0x00000020, .path = '/boot/lib' },
{ .handle = 0x36f07b69, type = 0x00010020, .path = '/bin' },
$ ls /
d  1        0 bin
d  1        0 boot
$ ls /boot/
d  1        0 lib
$ PATH=/system/apps:/system/bin:/boot/bin:/bin
$ ps
task-utils/walker: cannot open sysinfo: 2
WARNING: walk_root_job_tree failed: ERR_NOT_FOUND (-25)

ps命令还是执行失败,这是因为ps需要读取文件/dev/misc/sysinfo,但我们并未映射目录/dev。

我们重新执行namespace-test,将目录/dev也映射。

$ namespace-test /bin=/boot/bin /boot/lib=/boot/lib /dev=/dev
{ .handle = 0x62cdf50f, type = 0x00000020, .path = '/dev' },
{ .handle = 0x63bdf561, type = 0x00010020, .path = '/boot/lib' },
{ .handle = 0x6045f55f, type = 0x00020020, .path = '/bin' },
$ ls /
d  1        0 bin
d  1        0 boot
d  1        0 dev
$ ps
/boot/bin/sh: 2: ps: not found
$ PATH= PATH=/system/apps:/system/bin:/boot/bin:/bin
$ ps
TASK           PSS PRIVATE  SHARED NAME
j:1028                             root
  p:1043   1373.8k   1372k     28k bin/devmgr
  j:1082                           magenta-drivers
    p:1245  789.8k    788k     28k /boot/bin/acpisvc
    p:1659  249.8k    248k     28k devhost:root
    p:1720  645.8k    644k     28k devhost:misc
    p:1786  253.8k    252k     28k devhost:platform
    p:1955 7329.8k   7328k     28k devhost:pci#1:1234:1111
    p:2017   24.4M   24.4M     28k devhost:pci#3:8086:2922
  j:1103                           magenta-services
    p:1104  293.8k    292k     28k crashlogger
    p:1193  237.8k    236k     28k netsvc
    p:2291  509.8k    508k     28k sh:console
    p:2364  241.8k    240k     28k sh:vc
    p:2498  241.8k    240k     28k sh:vc
    p:2569  237.8k    236k     28k sh:vc
    p:6875  329.8k    328k     28k /boot/bin/namespace-test
    p:6960  381.8k    380k     28k /boot/bin/sh
    p:7047  249.8k    248k     28k /bin/ps
TASK           PSS PRIVATE  SHARED NAME

DONE!

好的,我们可以分为以下几个步骤来实现: 1. 创建GUI界面:在Qt Creator中新建一个工程,选择Qt Widgets Application类型,创建一个主窗口,添加需要的控件,包括一个文本框用于输入函数,一个按钮用于确认输入,一个按钮用于清除画布,一个按钮用于保存画布,一个QCustomPlot控件用于绘制函数图像。 2. 实现函数解析:通过调用QString的toStdString()函数将输入的函数转换成std::string类型,再使用数学表达式解析库来计算函数值。我们推荐使用muParserX库,可以在Qt工程中直接使用。 3. 绘制函数图像:定义一个函数,接收一个函数字符串,以及绘制参数(例如颜色、线宽等),然后通过遍历x轴坐标,计算出对应的y轴坐标,使用QCustomPlot控件绘制出函数图像。 4. 清除画布:定义一个函数,遍历所有已绘制的函数图像,删除它们,并重新绘制一个空白的坐标轴。 5. 保存画布:定义一个函数,调用QCustomPlot控件的saveJpg()函数,将当前绘制的图像保存为jpg格式。 下面是实现代码的示例,你可以在此基础上进行修改和完善: mainwindow.h: ```cpp #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "muparserx/muparserx.h" #include "qcustomplot/qcustomplot.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_confirmButton_clicked(); void on_clearButton_clicked(); void on_saveButton_clicked(); private: Ui::MainWindow *ui; mu::ParserX parser; QVector<QCPGraph*> graphs; QColor colors[5] = {Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta}; int colorIndex = 0; void drawFunction(QString function, QColor color, double lineWidth); void clearGraphs(); void saveGraph(); }; #endif // MAINWINDOW_H ``` mainwindow.cpp: ```cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> #include <QFileDialog> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 设置坐标轴范围和名称 ui->customPlot->xAxis->setRange(-10, 10); ui->customPlot->yAxis->setRange(-10, 10); ui->customPlot->xAxis->setLabel("x"); ui->customPlot->yAxis->setLabel("y"); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_confirmButton_clicked() { QString function = ui->functionEdit->text(); if(function.isEmpty()) { QMessageBox::warning(this, "Error", "Please input a function!"); return; } // 设置解析器变量和函数 parser.DefineVar("x", &mu::ParserX::Variable); parser.SetExpr(function.toStdString()); // 绘制函数图像 drawFunction(function, colors[colorIndex++ % 5], 2); } void MainWindow::on_clearButton_clicked() { clearGraphs(); } void MainWindow::on_saveButton_clicked() { QString filePath = QFileDialog::getSaveFileName(this, tr("Save Image"), "", tr("JPEG (*.jpg)")); if(!filePath.isEmpty()) { saveGraph(); ui->customPlot->saveJpg(filePath); } } void MainWindow::drawFunction(QString function, QColor color, double lineWidth) { QVector<double> xData, yData; double xMin = ui->customPlot->xAxis->range().lower; double xMax = ui->customPlot->xAxis->range().upper; double xStep = (xMax - xMin) / 100; for(double x = xMin; x <= xMax; x += xStep) { parser.SetVar("x", x); double y = parser.Eval(); xData.append(x); yData.append(y); } QCPGraph *graph = ui->customPlot->addGraph(); graph->setData(xData, yData); graph->setPen(QPen(color, lineWidth)); graphs.append(graph); ui->customPlot->replot(); } void MainWindow::clearGraphs() { for(auto graph : graphs) { ui->customPlot->removeGraph(graph); } graphs.clear(); ui->customPlot->replot(); } void MainWindow::saveGraph() { ui->customPlot->toPixmap().save("temp.jpg"); } ``` 在这个示例中,我们使用了muParserX库来进行函数解析,使用QCustomPlot控件来进行函数图像绘制。其中,drawFunction()函数用于绘制函数图像,clearGraphs()函数用于清除画布,saveGraph()函数用于保存画布,每个函数都有相应的按钮与之对应,可以在mainwindow.ui中设置。你需要自己安装muParserX库和QCustomPlot控件,这些库可以在Qt Creator中直接安装。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值