diff --git "a/docs/\347\216\260\345\234\272\350\265\233.md" "b/docs/\347\216\260\345\234\272\350\265\233.md" new file mode 100644 index 00000000..7e6204f5 --- /dev/null +++ "b/docs/\347\216\260\345\234\272\350\265\233.md" @@ -0,0 +1,90 @@ +# 现场赛 + +## splice 系统调用 bug + +1. 在管道未关闭时,没有循环阻塞读取读 len 个字节,而是直接读取一个批量,导致读取数量少了。 + + 解决方法:管道阻塞读取直到len个字节或管道关闭 + +2. 直接开了一个长为len的vec,写入时没有与总读取长度作比较将vec截断,导致写入长度超出读取长度,返回值偏高。 + + 解决方法:用读取长度截断vec + +3. 写入管道没有阻塞直到管道关闭或写入读取长度的字节,同 bug 1。 + + 解决方法:同 bug 1。 + +## git 支持 + +### 编译 + +git 需要 zlib、openssl、curl,本地版本只需要zlib + +#### 本地版本 + +##### zlib + +``` +CC=riscv64-linux-gnu-gcc ./configure --prefix=/home/crw/cross/rootfs --static +make install +``` + +##### git + +git 使用 musl-libc 编译会报错,目前我们使用 riscv64-linux-gnu-gcc 进行编译。 + +``` +./configure --prefix=/home/crw/cross/rootfs --host=riscv64-linux-gnu --without-iconv --with-zlib=/home/crw/cross/rootfs ac_cv_fread_reads_directories=true ac_cv_snprintf_returns_bogus=false CFLAGS="-static" +``` + +- ac_cv_fread_reads_directories=true ac_cv_snprintf_returns_bogus=false + + 不加这两个 flag 分别会遇到以下两个 check fail + + ``` + checking whether system succeeds to read fopen'ed directory... configure: error: in '/home/crw/cross/src/git': + ``` + + ``` + checking whether snprintf() and/or vsnprintf() return bogus value... configure: error: in '/home/crw/cross/src/git': + ``` + + 参考 + +- --without-iconv + + 不加会遇到以下错误 + + ``` + configure:6373: checking for old iconv() + configure:6393: riscv64-linux-gnu-gcc -c -g -O2 conftest.c >&5 + configure:6393: $? = 0 + configure:6395: result: no + configure:6421: checking whether iconv omits bom for utf-16 and utf-32 + ``` + +#### libcurl 支持 + +libcurl 依赖 openssl,二者都编译好后可以编译 git。 + +需要编译动态链接版本的 git 才能支持,暂不清楚原因 + +否则会在 `checking for curl_global_init in -lcurl... no` 失败。 + +### rootfs + +为了支持 git 运行,我们做了若干改动: + +- git 编译时指定 prefix 会静态将 prefix 里的路径写入到二进制中,如果 prefix 是 /home/crw/cross/rootfs,git 就会在静态地这个路径查找环境,因此我们在 rootfs 中添加了 prefix,以及 git 需要的配置文件,比如 /home/crw/cross/rootfs/etc/gitconfig +- git 会在静态编译的 prefix 目录下查找 /etc/gitconfig,如果没有,需要联网并使用 UnixSocket,目前内核对 UnixSocket 支持不完善,因此,我们在 /etc/gitconfig 下指定了用户名以及电子邮件 +- git pager 默认是 less,由于 tty 驱动对 termios 支持还不够完善,我们在配置文件里改成了 cat + +### ssh + +由于git测试有一个测试点的git clone需要ssh,正好在决赛第一阶段结束时我们打算支持sshd应用不过还没有完全支持成功,于是在现场赛继续尝试支持ssh协议,在rootfs上运行交叉编译openssh得到的ssh和sshd二进制文件,测试自己的操作系统是否支持ssh协议,完善网络部分,以便通过这个git clone测试点 + +- 运行sshd和ssh应用时发现其需要打开sshd_config和ssh_config等配置文件,于是我们在etc目录下添加了配置文件 +- 运行sshd出现了privilege separation相关的报错,发现这是由于之前在etc/passwd文件只有root这一个用户,我们新增了一个uid为1001的普通用户,简单支持了getuid和geteuid系统调用 +- ssh连接到sshd客户端时,ssh进程会通过setsockopt系统调用允许端口地址复用,使得ipv4和ipv6两种协议的tcp socket能绑定到同一个端口,我们增修改了了TDP socket的端口冲突检测允许了这种操作 + +由于编译git的riscv二进制联网版本花费了太久时间,导致没有时间做继续修复git clone时卡住的bug