首页
留言
关于
统计
友链
Search
1
[C++Quiz]#4、#116、#174
1 阅读
2
C/C++选手初学Python可能遇到的问题
0 阅读
3
[C++Quiz]#27、#41、#44
0 阅读
4
[C++Quiz]#185、#207、#219
0 阅读
5
[C++]std::variant
0 阅读
C/C++
数据结构与算法
CSLab
xv6
bustub
6.5840
数据库
doris
SQL
做个数据库
工具
CS
登录
Search
标签搜索
C++
cppquiz
xv6
算法
doris
论文
os
CS
leetcode
Git
tools
并发
6.5840
Koarz
累计撰写
24
篇文章
累计收到
4
条评论
首页
栏目
C/C++
数据结构与算法
CSLab
xv6
bustub
6.5840
数据库
doris
SQL
做个数据库
工具
CS
页面
留言
关于
统计
友链
搜索到
24
篇与
的结果
2023-10-27
[doris]doris编译环境
这是尝试doris编译的第n次,这玩意是真难搞...无数次尝试直接编译之后,我的建议是使用docker首先拉取镜像docker pull apache/doris:build-env-ldb-toolchain-latest拉取成功之后使用docker images查看是否拉取成功。之后可以下载你fork的doris源码,再使用docker挂载目录docker run -it --network=host --name mydocker -v /your/local/.m2:/root/.m2 -v /your/local/doris-DORIS-x.x.x-release/:/root/doris-DORIS-x.x.x-release/ apache/doris:build-env-ldb-toolchain-latest注意自己修改成你自己的目录(/your/local/..)。如果你因为某些原因开放端口,那样上网的话,打开docker之后你可能没法联网,这时候就需要把--network=host去掉,接下来就是thirdparty。thirdparty是真难搞,我尝试了无数次还是没编译好,而且有时候download-thirdparty还会下载不了,还得自己下好再放到src目录,这里我建议用编译好的,能省无数的事。https://github.com/apache/doris-thirdparty/releases/tag/automation,你可以在这里找到合适的资源下载,最后把installed文件夹放在你的doris/thirdparty/目录下即可,其他的可以看官方文档就行了,如果有其他问题,修改就行,最后在docker里运行build.sh就好
2023年10月27日
0 阅读
0 评论
0 点赞
2023-10-24
[xv6]资源汇总
对xv6需要的资源做的集合
2023年10月24日
0 阅读
0 评论
0 点赞
2023-10-21
[xv6]Lab1-Utilities
开始6.S081的学习了,在这里记录下我对xv6的理解以及我的题解,这里我会尽可能详细的写。我写了我的代码实现,但是肯定是不完善的,所以你最好都自己写,你如果实在写不出来,可以评论一句 “看看代码”。{dotted startColor="#ff6c6c" endColor="#1989fa"/}环境安装这个照着官网的 教程 来就行,注意一下自己的linux版本(ubuntu20.04)。sleep (easy)因为不知道该怎么开始,所以这个我是直接看写好的,知道了怎么开始才能继续下边的任务对吧。就是调用提供的sleep接口就行。#include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" int main(int argc, char *argv[2]) { if (argc < 2) { fprintf(2, "usage sleep <ticks>\n"); exit(1); } sleep(atoi(argv[1])); exit(0); }pingpong (easy)这个任务要求我们利用管道在两个进程之间通信,最后实现这样的效果:{card-describe title="pingpong"}$ make qemu ... init: starting sh $ pingpong 4: received ping 3: received pong ${/card-describe}管道是一个小的内核缓冲区,它以文件描述符对的形式提供给进程,一个用于写操作,一个用于读操作。从管道的一端写的数据可以从管道的另一端读取。管道提供了一种进程间交互的方式。xv6中我们可以使用pipe()函数创建管道,提到这个我们要先了解一下文件描述符。具体请自行查阅xv6文档,简单来说就是在一个进程中一些读写等操作需要文件描述符来确定,比如read(0, buf,sizeof buf);这里的0就是代表从这个“0”处读取,或者说输入端是0绑定的文件(注意这个0是文件索引)。我们创建一个管道之后,这个管道也有他的文件描述符。例如int p[2];pipe(p);这个管道的文件描述符就被保存在了p数组中。p[0]是管道的读端口,p[1]是管道的写端口,有了管道的文件操作符我们就可以操作管道了。这个任务既可以用一个管道也可以用两个管道,两个管道更容易理清关系,记得关闭无用描述符,比如p1在process1只写那么就close(p1[1])等等,双管道双进程关系如图: 一个管道也可以做,我就是一个管道做的,这样做有没有什么风险我不知道,但是确实可以用。在我的理解中单管道是这样工作的:首先在process1中fork出process2。process2在read时如果p[0]没有接收到数据并且process1的p[1]也没有关闭,所以无论怎样process2都会等待接收process1的数据,process1传输ping之后close(p[1]),process2接收ping再输出,此时process1也会被read阻塞,直到process2传入pong,这样就保证了顺序即使只有一个管道也不会乱。隐藏内容,请前往内页查看详情primes (moderate)/(hard)这个任务是让我们写出素数筛,具体实现请思考这张图: 思考完了吗?那我来讲讲实现吧。 首先呢一个进程只会输出一个数,之后他会接收上一个进程中已经筛过数继续筛,上图的drop就是被筛掉的数,我们可以看到在输出2的进程中4、6、8...等所有2的倍数都被drop了,通过筛选的第一个数也就是3会进入新进程并输出,第二个数5因为不被3整除且是输出3的进程的第一个通过筛选的数所以他又进入了一个新进程并被输出...以此类推,就完成了素数筛选。 然后讲讲我的实现方法,我使用了一个id作为一个进程的标识,这个id代表通过了上一个进程筛选的第一个数也就是确认的素数。首先这个进程输出这个id,或者输出之后再创建进程随你,之后它接收通过了上一个进程的筛选的数并使用自己来筛选,比如2筛选4、6、8,3筛选9这些,如果这个数通过,那么就传给下一个进程,如果它是第一个通过的,那么优先为它创建新进程并以它命名id,这样的工作持续到上一个进程的管道的写端口关闭,那么我们就关闭进程,上边的进程wait之后也相继关闭。 这方面请了解read,write,wait等系统调用。 我的文字描述可能有点不清晰,那请看图,相信你可以看懂的(我是做的时候为了自己能理清所以画了这张图,第一次觉得流程图这么有用) {alert type="info"}写的时候请思考每个管道应该什么时候关闭,不然你可能会遇到许多想不明白的问题。{/alert}隐藏内容,请前往内页查看详情find (moderate)find 需要我们实现查找文件功能,但是会遍历给定文件夹的所有子孙文件夹(我自己起的名字),接着输出所有名称与给定名称的一样的文件。这个函数给出的提示是让我们看ls的实现源码,接下来我们就好好分析一下ls部分的源码。void ls(char *path) { char buf[512], *p; int fd; struct dirent de; struct stat st; if((fd = open(path, O_RDONLY)) < 0){ fprintf(2, "ls: cannot open %s\n", path); return; } if(fstat(fd, &st) < 0){ fprintf(2, "ls: cannot stat %s\n", path); close(fd); return; } switch(st.type){ case T_DEVICE: case T_FILE: printf("%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size); break; case T_DIR: if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){ printf("ls: path too long\n"); break; } strcpy(buf, path); p = buf+strlen(buf); *p++ = '/'; while(read(fd, &de, sizeof(de)) == sizeof(de)){ if(de.inum == 0) continue; memmove(p, de.name, DIRSIZ); p[DIRSIZ] = 0; if(stat(buf, &st) < 0){ printf("ls: cannot stat %s\n", buf); continue; } printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size); } break; } close(fd); }这个是主体两个if里就是给文件描述符赋值并将文件的信息保存在stat中,在switch中如果给出的path不是文件夹那么就输出当前文件的一些信息,重点是在T_DIR中,while这里就是遍历了所有子文件。//通过while循环不断读取数据,我们可以看dirent的解释: Directory is a file containing a sequence of dirent structures. while(read(fd, &de, sizeof(de)) == sizeof(de)){ if(de.inum == 0) continue; memmove(p, de.name, DIRSIZ); p[DIRSIZ] = 0; if(stat(buf, &st) < 0){ printf("ls: cannot stat %s\n", buf); continue; } printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size); }知道了怎么遍历文件,剩下的就好做了,我们在遍历时候判断name是不是等于给定filename就行,当然如果是文件夹,那么我们进入这个文件夹再遍历,就是遇到文件就判断,遇到文件夹就递归,就完成了。隐藏内容,请前往内页查看详情xargs (moderate)这个我感觉比素数筛难,但是居然不带hard。首先呢,xargs就是执行它后边的程序也就是 xargs echo hello这样的,它接收管道的数据并加到hello之后,不过呢如果遇到换行\n,那就输出一行并继续执行相同操作,我这里描述的不太清晰,看个例子就明白了:echo hello\nworld | xargs echo say 这个不是很准确,因为\n会被识别成两个字符,但是我们假设这就是一个。程序是这样执行的:xargs echo say helloxargs echo say world看明白了吗?我们需要写一个字符串处理,就是把\n前和\n后的字符串分开,再用exec执行就行。通过分析,xargs的argv参数是这样的argv[0] = "xargs" argv[1] = "echo" argv[2] = "say"没有argv[3],也就是说我们要使用read对文件操作符0进行读取,注意read读取一次只读取一个单词,所以我们还需要能读一整行的函数,不然还没读到\n就输出了不是?因为没有意识到read只读一个单词(或者说一直读到空格和换行)我这个做了很长时间但是找不到问题在哪,还有根据xv6book的描述,参数argv是根据argv==0结束的,在传参时候我们要注意这点。隐藏内容,请前往内页查看详情
2023年10月21日
0 阅读
0 评论
0 点赞
2023-10-08
[C++]Windows环境下给Clion安装Boost库
Boost下载打开官网https://www.boost.org/你现在可以看到这个界面 你可以选合适的版本安装,保证你的CMAKE支持该版本即可,这里下载1.82 建议下载7z的,zip解压太慢了(至少在我电脑上是这样)点击bootstrap.bat后生成b2.exe文件,再点这个exe等他编译完就好了Clion的CMakeList文件的修改这是我的配置:cmake_minimum_required(VERSION 3.27.0) project(CPP23) set(CMAKE_CXX_STANDARD 23) set(Boost_DEBUG on) set(Boost_DETAILED_FAILURE_MSG ON) set(BOOST_ROOT D:/local/boost_1_82_0) set(BOOST_INCLUDEDIR ${BOOST_ROOT}/boost) set(BOOST_LIBRARYDIR ${BOOST_ROOT}/stage/lib) set(Boost_LIB_PREFIX "lib") set(Boost_ARCHITECTURE "-x64") find_package(Boost COMPONENTS REQUIRED) add_executable(CPP23 main.cpp) include_directories(${BOOST_ROOT}) target_link_libraries(CPP23 ${Boost_LIBRARIES})项目名称是CPP23,里边有一个main.cpp文件,BOOST_ROOT后边填写你的boost解压目录即可Boost编译时提示找不到vswhere,build engine找不到文件的解决办法直接先上结论,装一下VS就好了昨天准备在Clion上安装Boost库,但是Clion的Cmake版本不支持最新的1.83的Boost库,所以我就去下载了1.82版本的。但是这次下载之后我运行bootstrap.bat一直出错,无法生成b2.exe,于是我打开了booststrap.bat文件发现它会检测有没有生成b2文件,没有的话会运行build.bat,打开build.bat它是默认找Visual Studio的,但是我之前把VS删了所以一直没成功,这时候我忘了自己删了VS,就到网上各种查,甚至该build文件,最后发现都是多余了。上了床查了vswhere想到找找我的正确的目录,今天才发现是我给卸载了...
2023年10月08日
0 阅读
0 评论
0 点赞
2023-07-15
[C++]std::variant
{dotted startColor="#ff6c6c" endColor="#1989fa"/}std::variant介绍{message type="info" content="以下信息参考cppreference"/}{card-list}{card-list-item}在标头 定义{/card-list-item}{card-list-item}template <class... Types>class variant; (C++17 起) {/card-list-item}{/card-list}类模板 std::variant 表示一个类型安全的联合体。 std::variant 的一个实例在任意时刻要么保有其一个可选类型之一的值,要么在错误情况下无值(此状态难以达成,见 valueless_by_exception )。与联合体在聚合初始化中的行为一致, 若 variant 保有某个对象类型 T 的值,则直接于 variant 的对象表示中分配 T 的对象表示。不允许 variant 分配额外的(动态)内存。variant 不容许保有引用、数组,或类型 void 。空 variant 亦为病式(可用 std::variant<std::monostate> 代替)。variant 容许保有同一类型多于一次,而且可保有同一类型的不同 cv 限定版本。同联合体,默认构造的 variant 保有其首个选项的值,除非该选项不是可默认构造的(该情况下 variant 亦非可默认构造:能用辅助类 std::monostate 使这种 variant 可默认构造)。{card-describe title="模板形参"}Types - 可存储于此 variant 中的类型。所有类型必须满足可析构 (Destructible) 要求(特别是不允许数组类型和非对象类型)。 {/card-describe}std::variant的简单使用#include <iostream> #include <variant> using var_T = std::variant<int,double,char>; int main() { var_T v; v = 1;//给v复制int std::cout << std::get<int>(v) << ' ' << v.index() << '\n'; v = 2.5;//给v赋值double std::cout << std::get<double>(v) << ' ' << v.index() << '\n'; v = 'A';//给v赋值char std::cout << std::get<char>(v) << ' ' << v.index() << '\n'; v = "Hello cremache!" //error,v不能储存字符串类型 return 0; }输出:1 02.5 1A 2分析:示例给的 variant 可以储存int,double,char类型的数据,如果我们需要将v储存的值输出,那么就需要用到std::get<type>(var),但是这种输出需要你显式指出v储存的值的类型,auto 在这里是不能使用的,当然除了具体的数据类型,你也可以使用 0 代表 int ,1 代表 double ,2 代表 char(具体请根据你自己的定义,这里的012是根据我的定义)。除了std::get() C++还提供了std::get_if() ,get_if 同样需要显式指出数据类型,get_if的参数是指向 variant 的指针,返回值是指向存储于被指向的 variant 中值的指针,错误时为空指针。index()可以返回 variant 当前所保有的可选项的零基下标。若 variant 因异常无值( valueless_by_exception ),则返回 variant_npos 。通俗来说就是0是int,1是double(仅限示例)。{alert type="error"}需要额外注意的是如果你想这样使用std::get<v.index()>(v)那么就停留在想阶段,这样的代码是错误的。{/alert}在std::vector中使用std::variant#include <iostream> #include <variant> #include <vector> using var_T = std::variant<int,double,char>; template<class... Ts> struct overloaded : Ts... {using Ts::operator()...;}; template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; int main() { std::vector<var_T> n{ 2.5 , 'A', 1}; for(auto v : n) { std::visit(overloaded{ [](int arg) { std::cout << arg; }, [](double arg) {std::cout << std::fixed << arg;}, [](char arg) {std::cout << arg;}, },v); std::cout << '\n'; } return 0; }输出:2.50000A1这是cppreference给出的写法,我们需要使用visit()函数来访问数据,但是这种写法非常麻烦,这里有一个难懂的overloaded 在 Stack Overflow 中有大佬对overloaded做出解释:{alert type="info"}第一个 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; 是一个经典的类/结构声明/定义/实现。从C++11开始有效(因为使用了可变模板)。 在这种情况下,overloaded从所有模板参数继承,并使用了所有继承的operator()(使用了using语句)。这是Variadic CRTP的一个示例。 不幸的是,可变using语句只在C++17及以上版本中可用。 第二个 template<class... Ts> overloaded(Ts...) -> overloaded<Ts...> 是一个“推导指南”(详见此页面了解更多详情),它是C++17的一个新特性。 在你的情况下,推导指南表示当你写下如下代码时: auto ov = overloaded{ arg1, arg2, arg3, arg4 }; 或者 overloaded ov{ arg1, args, arg3, arg4 }; ov变成了overloaded<decltype(arg1), decltype(arg2), decltype(arg3), decltype(arg4)> 这允许你写出如下代码:overloaded { [](int arg) { std::cout << arg; }, [](double arg) {std::cout << std::fixed << arg;}, [](char arg) {std::cout << arg;}, } 在示例代码中还有另一个有趣的新C++17特性:基类的聚合初始化。 也就是说...当你写下如下代码时:overloaded { [](int arg) { std::cout << arg; }, [](double arg) {std::cout << std::fixed << arg;}, [](char arg) {std::cout << arg;}, }你是在初始化overloaded的三个基类时传递了三个lambda函数。 在C++17之前,只有在编写了显式构造函数时才能这样做。从C++17开始,它可以自动工作。 {/alert}但是这种写法我们可以简化!#include <iostream> #include <variant> #include <vector> using var_T = std::variant<int,double,char>; int main() { std::vector<var_T> n{ 2.5 , 'A', 1}; for(auto v : n) { std::visit([](auto arg){std::cout << arg;},v); std::cout << '\n'; } return 0; }直接使用使用auto推导类型,就不用我们分情况写了。当然,具体操作还是得根据具体情况使用。
2023年07月15日
0 阅读
0 评论
0 点赞
1
...
3
4
5