PB学习笔记(7.26)

1.常见问题(7.26)

  • 我总觉得讲义写得不清楚:毕业工作后,不会再有讲义具体地告诉你应该做什么, 总有一天你需要在脱离讲义的情况下完成任务. 我们希望你现在就放弃"讲义和框架代码会把我应该做的一切细节清楚地告诉我"的幻想, 为自己的成长负起责任:

    • 不知道在说什么, 说明你对知识点的理解还不够清楚, 这时候你应该去看书/看手册
    • 不知道要做什么/怎么做, 说明你的系统观好是零碎的, 理解不了系统中各个模块之间的联系, 这时候你应该RTFSC, 尽自己最大努力梳理并理解系统中的一切细节
    • bug调不出来, 说明你不清楚程序正确的预期行为, 你需要RTFSC理解程序应该如何运行; 此外也说明你不重视工具和方法的使用, 你需要花时间去体验和总结它们

    如果你发现自己有以上情况, 你还是少抱怨, 多吃苦吧.

    当然, 如果你仍然觉得讲义写得不清楚, 可以联系yzh.

  • PB的内容太丰富了,我感觉没办法完全消化:所以PB值得二周目。

2.Introduction

实验方案

理解“程序如何在计算机上运行”的根本途径是从“零”开始实现一个完整的计算机系统。本课程会指导学生实现一个经过简化但功能完备的x86/mips32/risv32(64)模拟器NEMU,最终在NEMU上运行游戏“仙剑奇侠传”,来让学生探究“程序在计算机上运行”的基本原理。

3.tmux(8.2)

3.1About tmuxGetting started

了解一下专业名词:

这里就不重复造轮子了,直接上链接shell、bash、terminal和kernel之间的关系 。

总结就是shell是一个壳程序(命令行),可以通过此shell来调用其他软件:man,gdb,gcc等。指的是能对操作系统和应用程序进行操作的接口程序

terminal说是终端,其实是一个终端软件,是一个可以运行shell命令的软件。

两者之间的关系:terminal是一个可以运行shell命令的终端模拟软件。

tmux是运行在terminal中的一个程序,并允许其他终端程序运行在其中。

tmux支持在运行程序时关闭终端窗口,后期可以再连接上终端(保护现场)。

tmux可以允许程序运行时全屏幕,像是vi或者bash。

tmux的主要用途是:

3.2 Basic concepts

The tmux server and clients

tmux在一个运行在后台的主进程中持有它的所有状态信息。用户使用tmux,就像是客户连接tmux一样,用户的tmux通知停止,tmux的服务器端便停止服务。

将tmux和用户使用tmux的场景,比作sever和client的交互方式,的确相当新奇。

Sessions, windows and panes

在路易斯的Tmux使用手册中,对于本节的介绍十分精彩:

tmux采用C/S模型构建,输入tmux命令就相当于开启了一个服务器,此时默认将新建一个会话,然后会话中默认新建一个窗口,窗口中默认新建一个面板。会话、窗口、面板之间的联系如下:

一个tmux session(会话)可以包含多个window(窗口),窗口默认充满会话界面,因此这些窗口中可以运行相关性不大的任务。

一个window又可以包含多个pane(面板),窗口下的面板,都处于同一界面下,这些面板适合运行相关性高的任务,以便同时观察到它们的运行情况。

pane:每一个运行在tmux中的terminal都是一个面板,这个pane会展示termianl的数据。多个pane组合在一起,可视化效果(多窗口)非常好。

window:有自己的默认姓名,但也可以被更改。姓名不是区分不同和窗口的特征,它的连接和窗口索引才是。

Linux session介绍了什么是Linux Session,方便理解本节的概念。概览:当我们打开一个新的终端时,总会创建一个新的 shell session。可以理解一个终端就是一个session。

大体了解了其中的概念,时间已经到了7:04,整理完本章节后,练习一会打字就该上班了。

在本节的术语总结中,也介绍了session,windoews and panes。

Term Description
Window Groups one or more panes together, linked to one or more sessions
Pane Contains a terminal and running program, appears in one window
Session Groups one or more windows together

3.3 Using tmux interactively(8.4)

Creating sessions

tmux new -s mysession #give the session a specified name
tmux new              #new-session for short

The status line

When a tmux client is attached,it shows a status line on the bottom line of the screen.

The prefix key

一旦tmux客户机连接了,任何键盘的输入都会进入当前窗口的活跃窗格中。

prefix key(前缀键),举例C-b c :Ctrlb同时按下,然后释放,松开后再按c

Help keys

C-b ? enters view mode to show text which has a short description to help remember what the key does.

C-b ? 简单描述快捷键怎么用的模式。

粘贴几条自认为常用的快捷键吧

C-b "   #split window vertically
C-b %   #split window horizontallyC-b &   #kill current window
C-b x   #kill the active paneC-b (  #switch to previous client
C-b )  #switch to next client
C-b c  #create a new window
C-b n  #select the next windowC-b w  #choose a window from a list
C-b s  #choose a session from a list

Commands and flags

每当使用一个按键组合,tmux就会执行一个或者多个命令。像是C-b c就是执行了new-window命令。

All commands and their flags are documented in the tmux manual page.

就是STFM。$ man tmux走起,但是现在只是按需操作。

4.GDB(8.15)

预计GDB学习在8月19号结束,现在主要是把100个GDB小技巧的前6讲速通,达到一个大体了解gdb的工作内容的作用。

今天已经是8月18号了。

5.Git(8.30)

今天是学习git的一天,并且在今明两天,我将会把git的基本概念和基本操作弄懂。本学习内容的参考如下:

  • Git(廖雪峰版本)
  • git - 简明指南

5.1基础概念

正如作者写的:

本教程只会让你成为Git用户,不会让你成为Git专家。很多Git命令只有那些专家才明白(事实上我也不明白,因为我不是Git专家),但我保证这些命令可能你一辈子都不会用到。既然Git是一个工具,就没必要把时间浪费在那些“高级”但几乎永远不会用到的命令上。一旦你真的非用不可了,到时候再自行Google或者请教专家也未迟。

在我们学习PA的路线中,Git只能说是需要掌握的一个工具,而不是需要专门学习精通的生存技能。利用好各种工具来完成最终的abstract-mechine成功运行才是至关重要的。

所有新工具的使用,不要超过2天学习,按照教程大体流程走一遍,有个大体印象,等以后有需求了,再回头看!

不要让自己卡在工具层面太久,分清任务的主次,施行多轮重复滚动学习的方法,减少自己的学习挫败感。

Git是分布式版本控制系统,**分布式和集中式**的区别:

名称 区别
分布式版本控制系统 1.每个电脑都是一个完整的版本库,安全性高;2.多人协作,只需要把各自的修改发送给对方,协作方便;3.可以不联网
集中式版本控制系统 1.需要一个中央服务器来存储版本,操作数据只能下载后修改然后将编辑后的内容提交,协作麻烦;2.一个中央服务器的存储,带来的就是存储数据的安全性风险极高;3.必须联网才能操作

什么是版本控制系统?例如自己写一个类似typora的md文件。如果你想删除一段段落,或者修改一些文字描述,但是又不希望丢失这些改动,以便未来提示你,在何时修改了什么地方。那么一个纯文本文件是无法做到记录修改操作的,那么就需要复制一个新的文件,在此基础上进行修改操作,人工通过空间(建立多个文件副本)和时间(多个文件的命名区分、内容比对),换取修改内容的版本控制需求。

并且,如果有其他人要修改你的文件,并且人家可能不遵循你的修改原则的话,那么文件的维护将会变得异常艰难。那么一个能够自动记录每次文件的改动的软件,并且还能让同事协作编辑,不需要自己再维护管理一堆文件副本,版本控制系统就应运而生了。想知道修改了什么,直接查看自己的修改记录即可。这就是版本控制系统。

那么还有几个重要的概念:需要着重理解分支

5.2功能介绍

#安装
sudo apt-get install git#配置用户名和email地址
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
  • 创建版本库:创建一个能被git管理的目录,这个目录的所有文件都能被git管理起来,即文件的修改、删除,都能记录下来。相关命令就是

    mkdir test
    cd test
    git init
    
  • you can list all branches by

    git branches
    
  • This command will create a branch called pa0, and check out to it

    git checkout -b pa0
    

    这样在pa0上所作的操作,便不会影响到master分支上的文件,可以说非常的nice。

6.PA0学习尾部

git操作nemu的初步编译问题调试。

nemu/文件夹下执行make menuconfig的时候,发现很多工具没有安装,于是乎按照要求安装所需要的软件即可。安装完了以后继续执行make menuconfig的时候,提示

+ CC src/memory/paddr.c
+ CXX src/utils/disasm.cc
src/utils/disasm.cc:5:10: fatal error: llvm/Support/TargetRegistry.h: No such file or directory5 | #include "llvm/Support/TargetRegistry.h"|          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [/home/crx/ics2021/nemu/scripts/build.mk:40: /home/crx/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/disasm.o] Error 1

经过stackoverflow的启发Stackoverflow:llvm/Support/TargetRegistry.h: No such file or directory,知道了是编译(8月31号开始)src/utils/disasm.cc的时候,出现了文件引用失败。这时候用到了一个命令apt-file来寻找这个TargetRegistry.h文件。在这里简单介绍下apt-file 的作用 apt-file。

apt-file:apt-file is a command line tool for searching files in packages for the APT package management system。apt-file 是一个命令行界面的 APT 包搜索工具。当我们在编译源代码时,时有缺少文件的情况发生。此时,通过 apt-file 就可以找出该缺失文件所在的包,然后将缺失的包安装后即可让编译顺利进行了。所以当我们通过执行命令

apt-file search TargetRegistry.h

后,可以发现

crx@crx-virtual-machine:~/ics2021/nemu$ apt-file search TargetRegistry.h
llvm-11-dev: /usr/include/llvm-11/llvm/Support/TargetRegistry.h
llvm-12-dev: /usr/include/llvm-12/llvm/Support/TargetRegistry.h
llvm-13-dev: /usr/include/llvm-13/llvm/Support/TargetRegistry.h
llvm-14-dev: /usr/include/llvm-14/llvm/MC/TargetRegistry.h

可以发现llvm的版本在14之前,TargetRegistry.h文件都放在llvm/Support/文件下。但是当版本升级到14的时候,文件夹就变了,那么查看下自己linux安装的llvm的版本:

llvm-as --version

可以得到

Ubuntu LLVM version 14.0.0Optimized build.Default target: x86_64-pc-linux-gnuHost CPU: alderlake

所以可以解决TargetRegistry.h文件缺失问题了:因为当前我们的llvm版本是14,TargetRegistry.h文件在/llvm/MC/下,而不是src/utils/disasm.cc文件的#include "llvm/Support/TargetRegistry.h",所以知道错误,直接去disasm.cc的文件中将头文件的位置修改好即可。改完后,即可执行make,编译就成功了。昨晚11点睡的,所以6:50起床还是可以接受的。现在是7:35了,准备准备上班去了。

昨晚11点睡的,所以6:50起床还是可以接受的。现在是7:35了,准备准备上班去了。

晚上回来的时候,已经是7:50左右了,洗洗衣服,到了8点。这时候准备运动40分钟,便接了水,跑了三公里,做了15个俯卧撑和拉伸运动。回来后,脱衣,玩塞尔达到22:30分,打开PA,准备继续。

然后就是下一步:make run,执行后,返回信息为:

crx@crx-virtual-machine:~/ics2021/nemu$ make run
+ LD /home/crx/ics2021/nemu/build/riscv32-nemu-interpreter
/home/crx/ics2021/nemu/build/riscv32-nemu-interpreter --log=/home/crx/ics2021/nemu/build/nemu-log.txt
[src/utils/log.c:13 init_log] Log is written to /home/crx/ics2021/nemu/build/nemu-log.txt
[src/memory/paddr.c:36 init_mem] physical memory area [0x80000000, 0x88000000]
...
...
[src/monitor/monitor.c:17 welcome] Build time: 22:34:26, Aug 31 2022
Welcome to riscv32-NEMU!
For help, type "help"
[src/monitor/monitor.c:20 welcome] Exercise: Please remove me in the source code and compile NEMU again.
riscv32-nemu-interpreter: src/monitor/monitor.c:21: welcome: Assertion `0' failed.
make: *** [/home/crx/ics2021/nemu/scripts/native.mk:23: run] Aborted (core dumped)

看最后三行的提示信息:

[src/monitor/monitor.c:20 welcome] Exercise: Please remove me in the source code and compile NEMU again.
riscv32-nemu-interpreter: src/monitor/monitor.c:21: welcome: Assertion `0' failed.
make: *** [/home/crx/ics2021/nemu/scripts/native.mk:23: run] Aborted (core dumped)

提示我们这是一个小测试,需要在源码中将某个地方移除,再次执行编译NEMU的操作。那么这个文件很明显是src/monitor/monitor.c,位置是在此文件的21行。定位到此文件,查看此文件代码:

static void welcome() {Log("Trace: %s", MUXDEF(CONFIG_TRACE, ASNI_FMT("ON", ASNI_FG_GREEN), ASNI_FMT("OFF", ASNI_FG_RED)));....printf("For help, type \"help\"\n");Log("Exercise: Please remove me in the source code and compile NEMU again.");assert(0);//-------------------21行代码
}

assert()函数报错了。查询下此函数的用途:C语言assert函数

函数特性:void assert( int expression ),expression是条件判断或表达式。assert将通过检查表达式expression的值来决定是否要终止程序。当表达式expression的值为假(即为0),那么它将首先向标准错误流stderr打印一条出错信息,然后再通过调用abort函数终止程序;expression表达式为真,assert便无作用。

得知assert函数的作用后,将此行代码注释掉,再回到nemu\顺序执行

make clean --> make -->make run

就可以看到(nemu)已经成功启动了。今天的学习到此为止吧,明天继续学习记录吧!

9月1号:PA0文档的末尾,告诉我遇到我问题,需要

  • STFW
  • RTFM
  • RTFSC

再执行完合并分支的操作

git commit --allow-empty -am "before starting pa1"
git checkout master
git merge pa0
git checkout -b pa1

就来到了下一个场景:PA1:最简单的计算机。

PA1:开天辟地的篇章: 最简单的计算机(9.1)

  • task PA1.1: 实现单步执行, 打印寄存器状态, 扫描内存
  • task PA1.2: 实现算术表达式求值
  • task PA1.3: 实现所有要求, 提交完整的实验报告

做PA的终极目标是通过构建一个简单完整的计算机系统, 来深入理解程序如何在计算机上运行. 和那些"用递归实现汉诺塔"的程序设计作业不同, 计算机系统比汉诺塔要复杂得多. 这意味着, 通过程序设计作业的训练方式是不足以完成PA的, 只有去尝试理解并掌握计算机系统的每一处细节, 才能一步步完成PA.

所以, 不要再用程序设计作业的风格来抱怨PA讲义写得不清楚, 之所以讲义的描述点到即止, 是为了强迫大家去理清计算机系统的每一处细节, 去推敲每一个模块之间的关系, 也是为了让大家积累对系统足够的了解来面对未知的bug.

这对你来说也许是一种前所未有的训练方式, 所以你也需要拿出全新的态度来接受全新的挑战.

(9.4)上述是PA对个人的态度要求,也就是强制自己去理解一些代码背后的逻辑,站在整体去看待代码。

这两天回去后放松了放松,因为自己有点累。周天再次拿到PA,感到非常快乐。不多谈,记录下自己的学习吧。

(9.6)昨晚工地施工2点多还叮叮当当,打了12345了已经,如果不管事,那么我得换宿舍了。

记录下自己今天请假下的PA记录吧。

在编译运行PA附带的任天堂红白机模拟器之前,为了让按键匹配,需要运行按键测试。在am-kernels/tests/am-tests目录下,运行make ARCH=native mainargs=k run的时候,出现了以下错误。

In file included from /home/crx/ics2021/abstract-machine/am/src/native/vme.c:3:
/home/crx/ics2021/abstract-machine/am/src/native/platform.h:23:11: error: variably modified ‘sigstack’ at file scope23 |   uint8_t sigstack[SIGSTKSZ];|           ^~~~~~~~

粘一下platform.h的代码:

│  2 #define __PLATFORM_H__
│  3
│  4 #include <am.h>
│  5 #include <unistd.h>
│  6 #include <signal.h>
│  7 #include <klib.h>
│  8 #include <klib-macros.h>
│  9
│ 10 void __am_get_example_uc(Context *r);
│ 11 void __am_get_intr_sigmask(sigset_t *s);
│ 12 int __am_is_sigmask_sti(sigset_t *s);
│ 13 void __am_init_timer_irq();
│ 14 void __am_pmem_map(void *va, void *pa, int prot);
│ 15 void __am_pmem_unmap(void *va);
│ 16
│ 17 // per-cpu structure
│ 18 typedef struct {
│ 19   void *vm_head;
│ 20   uintptr_t ksp;
│ 21   int cpuid;
│ 22   Event ev; // similar to cause register in mips/riscv
│ 23   uint8_t sigstack[SIGSTKSZ];
│ 24   //uint8_t sigstack[8192];
│ 25 } __am_cpu_t;
│ 26 extern __am_cpu_t *__am_cpu_struct;
│ 27 #define thiscpu __am_cpu_struct
│ 28
│ 29 #endif

错误描述是:variably modified ‘sigstack’ at file scope,即用变量修改了数组sigstack。通过STFW可以发现应该是C语言中关于变量存储的问题,借此机会,学习下《C primer plus》的第12章中关于作用域的知识。(话说好久没有回去看这本书了…)

2.1 作用域

作用域是描述程序中可访问标识符的区域。一个变量在内存中占有一定的的物理内存空间,在C语言中这样的一块存储变量的空间,称为对象(区分面向对象的“对象”)。

作用域有以下几个:

  • 函数作用域(function scope)
  • 函数原型作用域(function prototype scope):函数原型作用域的范围是从形参的声明到形参的结束。编译器在处理函数原型的时候,只关心它的类型,对于形参名(可有可无)通常无关紧要。即使有形参名,也不必与函数定义中的形参名相匹配。
  • 文件作用域(file scope):具有文件作用域的变量,从它的定义处到该文件所在的文件末尾都是可见的。

翻译单元和文件:

头文件(.h文件)可能会依次包含其他头文件,所以会包含多个单独的物理文件。但是,C预处理的时候,会将#include指令替换为包含头文件的内容。所以,在编译的时候,源代码和所有的头文件都看成是一个包含信息的单独文件。这个单元被称为翻译单元。描述一个具有文件作用域的变量时,它的实际可见范围是整个翻译单元。

2.2 ccache

Ccache is a compiler cache. It speeds up recompilation by caching previous compilations and detecting when the same compilation is being done again. Ccache is free software, released under the GNU General Public License version 3 or later. See also the license page.

为什么选择ccache作为编译项目:ccache 的基本原理是通过将头文件高速缓存到源文件之中而改进了构建性能,因而通过减少每一步编译时添加头文件所需要的时间而提高了构建速度。ccache高速编译工具这篇文章对于ccache的相关特性做了一些介绍。

ccache工具会高速缓存编译生成的信息,并在编译的特定部分使用高速缓存的信息,比如头文件,这样就节省了通常使用 cpp 解析这些信息所需要的时间。举例编译Example,假定 foobar.h 中包含对其他头文件的引用,ccache 会用那个文件的 cpp-parsed 版本(已编译过并被ccache缓存在cache中的备份)来取代 include 声明,而不是真正去读取、理解并解释其内容,ccache 只是将缓存在高速缓存中最终的文本拷贝到文件中,使得它可以立即被编译。(from:ccache高速编译工具)

作为一个RTFM的练习, 接下来你需要阅读man ccache中的内容, 并根据手册的说明, 在.bashrc文件中对某个环境变量进行正确的设置. 如果你的设置成功, 重新运行which gcc, 你将会看到输出变成/usr/lib/ccache/gcc. 如果你不了解环境变量和.bashrc, STFW.

so,首先STFW关于两个名词.bashrc环境变量。首先是简单介绍:

  • .bashrc:是bash存储一些定制功能的文件。为了加载你的配置,bash 在每次启动时都会加载 .bashrc 文件的内容。每个用户的 home 目录都有这个 shell 脚本。它用来存储并加载你的终端配置和环境变量(This shell script is found in each user’s home directory. It’s used to save and load your terminal preferences and environmental variables.)。What Is bashrc and Why Should You Edit It
  • 环境变量:(今天阅读完这个就玩会塞尔达!9.6)输入的命令的时候,就是靠PATH variable来找到你输入的的命令位置。

查询环境变量的时候,收获了一个宝藏网站:A guide for Linux.
这时候,出现了一个新命令ln,它的功能是为某一个文件A在另外一个位置建立一个同步的链接, 一种是hard link,又称为硬链接;另一种是symbolic link,又称为符号链接。通俗一点理解,可以把硬链接当成源文件的副本,他和源文件一样的大小,但是事实上却不占任何空间。符号链接可以理解为类似windows一样的快捷方式。下面就简单介绍下ln命令的用法。

  • 硬链接:

    crx@crx-virtual-machine:~/test/txtVim$ sudo ln ../gdbTest/test.c ln_test
    crx@crx-virtual-machine:~/test/txtVim$ ll
    total 20
    drwxr-xr-x 2 root root 4096 Sep  8 22:23 ./
    drwxr-xr-x 4 root root 4096 Aug  9 22:18 ../
    -rw-r--r-- 1 root root   11 Jul 28 09:48 f1
    -rw-r--r-- 1 root root   20 Jul 28 08:54 f2
    -rw-r--r-- 2 root root  264 Sep  8 22:07 ln_test
    

    可以看到一个ln_test文件就被创建出来了。因为是硬链接,修改其中的内容,相应的test.c文件也会被修改。

  • 符号链接:使用ln命令的“-s”参数来创建目录的符号链接,并使用ls命令来查看链接文件的详细信息:使用ln命令的“-s”参数来创建目录的符号链接,并使用ls命令来查看链接文件的详细信息:

    crx@crx-virtual-machine:~/test/txtVim$ sudo ln -s ../gdbTest dir1
    crx@crx-virtual-machine:~/test/txtVim$ ll
    total 20
    drwxr-xr-x 2 root root 4096 Sep  8 22:29 ./
    drwxr-xr-x 4 root root 4096 Aug  9 22:18 ../
    lrwxrwxrwx 1 root root   10 Sep  8 22:29 dir1 -> ../gdbTest/
    -rw-r--r-- 1 root root   11 Jul 28 09:48 f1
    -rw-r--r-- 1 root root   20 Jul 28 08:54 f2
    -rw-r--r-- 2 root root  264 Sep  8 22:07 ln_test
    

    可以看到把上一级的gdbTest/以符号链接的形式放到了本目录的dir链接,执行cd dir1命令

    crx@crx-virtual-machine:~/test/txtVim$ cd dir1
    crx@crx-virtual-machine:~/test/txtVim/dir1$ ll
    total 60
    drwxr-xr-x 2 root root  4096 Sep  4 15:41 ./
    drwxr-xr-x 4 root root  4096 Aug  9 22:18 ../
    -rw-r--r-- 1 root root    54 Aug 24 20:35 add.c
    -rw-r--r-- 1 root root    74 Aug 24 20:32 add.h
    -rwxr-xr-x 1 root root 16008 Aug 24 20:48 main*
    

    可以看到的确是进入了gdbTest/的目录。

**NEMU是什么?**同样地, NEMU就是一个模拟出来的计算机系统, 物理计算机中的基本功能, 在NEMU中都是通过程序来实现的. 要模拟出一个计算机系统并没有你想象中的那么困难. 我们可以把计算机看成由若干个硬件部件组成, 这些部件之间相互协助, 完成"运行程序"这件事情. 在NEMU中, 每一个硬件部件都由一个程序相关的数据对象来模拟, 例如变量, 数组, 结构体等; 而对这些部件的操作则通过对相应数据对象的操作来模拟. 例如NEMU中使用数组来模拟内存, 那么对这个数组进行读写则相当于对内存进行读写。

NEMU是一个模拟计算机,拥有计算机的所有功能,不过支持计算机的硬件是用软件模拟出来的罢了。

框架代码内容众多, 其中包含了很多在后续阶段中才使用的代码. 随着实验进度的推进, 我们会逐渐解释所有的代码. 因此在阅读代码的时候, 你只需要关心和当前进度相关的模块就可以了, 不要纠缠于和当前进度无关的代码, 否则将会给你的心灵带来不必要的恐惧.

bash技巧:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.comecho "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

我们可以在执行shell脚本时,向脚本传递参数,脚本内获取的参数格式为:$n

n代表一个数字,1为执行脚本的第一个参数,2为执行脚本的第二个参数,以此类推。特别的:$0是打印执行的文件名,$*一个字符串打印所有向脚本传递的参数。"$*" 把所有参数合并成一个字符串,而 "$@" 会得到一个字符串参数数组。可以写一个脚本testparams.sh,这个脚本分别遍历"$*""$@" 扩展后的内容,并打印出来。

#!/bin/bashfor arg in "$*"; doecho "****:" $arg
done
echo --------------
for arg in "$@"; doecho "@@@@:" $arg
done

修改权限后执行:

$ ./testparams.sh This is a test
****: This is a test
--------------
@@@@: This
@@@@: is
@@@@: a
@@@@: test

可以看到,"$*" 只产生一个字符串,for 循环只遍历一次。
"$@" 产生了多个字符串,for 循环遍历多次,是一个字符串参数数组。Bash技巧:介绍 $0、$1、 2 、 2、 2、#、 @ 、 @、 @、*、$? 的含义.

(10.7)

提升自己的整体能力,而不是把精力放到目标上。越来越发现PA是对人综合能力的磨练,我希望通过这次磨练,让自己更加喜欢计算机科学。So,let’s go!

然后发现自己对于nemu_main.c文件的C预处理指令有点摸不到头脑(没学过),现在正在学习《C primer plus》的第十六章C预处理器和C库

11.7号

最近放飞自我了哈哈哈。最近通关了《C primer plus》的第十六章C预处理器和C库,项目上线了继续学习吧。

NJ大学PA学习记录相关推荐

  1. 关于学习中国大学MOOC国家精品课程《计算机程序设计C++》的学习记录与小结

    上个月想学习一下C++,查询了MOOC上有本校的国家精品课程,立马就中途加入了这门课这学期的学习. (hh,授课的老师竟然还有我认识的几位) 总体来说,这门课对于C++的入门还是很好的,讲解的知识点也 ...

  2. Opencv 入门篇学习记录(图片)

    title: Opencv 入门篇学习记录(图片) Opencv 入门篇学习记录(图片) 前言 很早以前就接触Python了,大学的时候还自学了一段时间去做了课设,写了一些最速梯度下降法.黄金分割法. ...

  3. 基于微信小程序的学习记录与提醒应用设计与实现-计算机毕业设计源码+LW文档

    摘  要 网络的广泛应用给生活带来了十分的便利.所以把学习记录与提醒应用管理与现在网络相结合,利用java技术建设学习记录与提醒应用app,实现学习记录与提醒应用的信息化.则对于进一步提高学习记录与提 ...

  4. linux个人学习记录

    linux学习记录 资料: Linux 黑马程序员_bilibili AcWing Linux基础课 可能是东半球最全面易懂的 Tmux 使用教程! Shell 教程 | 菜鸟教程 (runoob.c ...

  5. 纽约大学深度学习PyTorch课程笔记(自用)Week3

    纽约大学深度学习PyTorch课程笔记Week3 Week 3 3.1 神经网络参数变换可视化及卷积的基本概念 3.1.1 神经网络的可视化 3.1.2 参数变换 一个简单的参数变换:权重共享 超网络 ...

  6. C++ Primer Plus 学习记录(第五章节-包含练习题答案)

    C++ Primer Plus 学习记录(第五章节-包含练习题答案) 5.1 for循环 5.1.1 for循环的组成部分 1.for循环的组成部分所完成的步骤 2.赋值表达式有值 3.cout中显示 ...

  7. Cooperative Perception协同感知学习记录

    Cooperative Perception协同感知学习记录 文章目录 Cooperative Perception协同感知学习记录 1. 首先介绍一篇不错的Revision文章:Deep Multi ...

  8. IDL学习记录和Java调用IDL方法

    IDL学习记录和Java调用IDL方法 2018年02月06日 08:32:02 回首1949 阅读数:385更多 个人分类: 随想 版权声明:乐呵乐呵得了 https://blog.csdn.net ...

  9. 无线通信零基础学习记录(2)——GSM空中接口物理层的设计

    无线通信零基础学习记录(2)--GSM空中接口物理层的设计 本章解释清楚了之前未搞懂的名词,如时隙等,以及各种信道类型,在此一并总结. TDMA空中接口技术 时分多址(TDMA,Time Divisi ...

最新文章

  1. 计算机多媒体运用的ppt课件,《计算机多媒体》PPT课件.ppt
  2. android gridview 加载图片大小,Gridview有两列和自动调整大小的图像
  3. [afterCode] docker 速成班 1: image
  4. Csharp: 拼音转汉字字符搜索字符串
  5. shell脚本逻辑判断,文件目录属性判断,if,case用法
  6. 如何设计一个良好的接口?
  7. Android 让系统自动生成缩略图并写入媒体库
  8. 3-07. 求前缀表达式的值(25) (ZJU_PAT数学)
  9. karaf osgi_在OSGi中为Karaf构建Camel-CXF REST服务–组播和聚合
  10. 用python爬虫爬取无水印图片_使用python 爬虫,爬取图片
  11. Egg框架入门教程合集之插件/工具/教程/专栏/开源项目
  12. 聊天机器人-ChatterBot初试
  13. (转)基于Metronic的Bootstrap开发框架经验总结(9)--实现Web页面内容的打印预览和保存操作...
  14. [Android] AsyncTask详解
  15. 数据产品经理面试提问集
  16. ISO14229-1道路车辆-统一诊断服务(UDS)-1
  17. 用php做动态时钟,时钟转动动图 如何制作转动的钟表动画?怎么做出时钟转动效果?时钟走动的动态图...
  18. cp -r命令 linux什么意思,linux系统里cp指的是什么意思
  19. 快速隐藏/取消隐藏工作表
  20. 硬件工程师成长之路(10)——项目举例

热门文章

  1. SQL创建视图时设置默认值
  2. 探索qq发送png透明通道丢失的问题
  3. 如何用AI做出一朵花
  4. 单例模式的具体实现(包含饿汉模式和懒汉模式)
  5. vue 设置所有的输入框只读_elementUI 设置input的只读或禁用的方法
  6. 设计模式——Mediator(中介者)模式
  7. 呵呵……今天看到个很有意思的FLASH贴上来共享快乐!
  8. UI设计交互逻辑和常用工具
  9. c语言环形队列用法,C语言,环形队列
  10. 切比雪夫距离公式证明