NJU/2019/OS

Description:

CODE:

Main.cpp:

 /*
@author: Edwin Xu
@Date:2019/11/13
@Note: just ASCII
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <iostream>
#include <vector> #define IMG_PATH "a.img" using namespace std; //myPrint in NASM
extern "C" {void myPrint(char *c,int len,int color);}
//print func using myPrint()
char chars[];
void print(string s,int color){
const char * c = s.c_str();
strcpy(chars,s.c_str());
myPrint(chars,s.length(),color);
} //Part1: struct and util functions
struct File
{
string filename;
int size;
int firstCluster;
File(string n, int s, int cluster) {
filename = n;
size = s;
firstCluster = cluster;
}
File(){
size = ;
filename = "";
firstCluster = ;
}
};
struct Directory
{
string dirName ;
//子目录
vector <Directory>subDirs ;
//当前文件夹的文件
vector <File>subFiles ;
int dirNum=;
int fileNum=; void addDir(Directory d) {
this->subDirs.push_back(d);
dirNum++;
}
void addFile(string name,int size,int cluster) {
this->subFiles.push_back(File(name,size,cluster));
fileNum++;
} Directory() {
dirName = "";
}
Directory(string n) {
this->dirName = n;
} //判断有没有son这个儿子
int hasSon(string son) {
for (int i = ; i < dirNum; i++) {
if (son.compare(subDirs[i].dirName) == ) {
return ;
}
}
return ;
}
//判断有没有这个file, 并返回cluster
int hasFile(string file) {
for (int i = ; i < fileNum; i++) {
if (file.compare(subFiles[i].filename) == ) {
return subFiles[i].firstCluster; //存在文件,返回cluster
}
}
return -; //不存在文件,返回-1
} }; vector<string> path; //当前已经遍历的目录 string getPath() {
string res = "/";
for (int i = ; i < path.size(); i++) {
res += (path[i] + "/");
}
return res ;
} void ls_display(Directory d) {
if (d.dirName.length()>) path.push_back(d.dirName); //if not root dir
print(getPath()+":\n",);
if(d.dirName.length()>) print(". .. ",);
for (int i = ; i < d.dirNum; i++) {
print(d.subDirs[i].dirName+" ",);
}
for (int i = ; i < d.fileNum; i++) {
print(d.subFiles[i].filename+" ",);
}
print("\n",);
for (int i = ; i < d.dirNum; i++) {
ls_display(d.subDirs[i]);
}
if (d.dirName.length() > )
{
path.pop_back();
}
} void ls_l_display(Directory d) {
if (d.dirName.length() > ) path.push_back(d.dirName); //if not root dir
print(getPath() +" " + to_string(d.dirNum) + " " + to_string(d.fileNum)+":\n",);
if (d.dirName.length() > ) print( ".\n..\n",);
for (int i = ; i < d.dirNum; i++) {
print(d.subDirs[i].dirName,);
print(" " + to_string(d.subDirs[i].dirNum) + " " + to_string(d.subDirs[i].fileNum)+"\n",);
}
for (int i = ; i < d.fileNum; i++) {
print(d.subFiles[i].filename +" " + to_string(d.subFiles[i].size)+"\n",);
}
print("\n",);
for (int i = ; i < d.dirNum; i++) {
ls_l_display(d.subDirs[i]);
}
if (d.dirName.length() > ) path.pop_back();
} /*
get dir node by dir name (note: name is unique)
*/
Directory getDirectory(Directory beginDir,string dirName) {
if (beginDir.dirName.compare(dirName) == ) {
return beginDir; //get it, the current dir is what i want
}
//fond in the subdir:
for (int i = ; i < beginDir.dirNum; i++) {
Directory temp_dir= getDirectory(beginDir.subDirs[i], dirName);
if (temp_dir.dirName.length() != )return temp_dir;
}
return Directory();
} //Part2: BPB and FAT operations typedef unsigned char u8; //1B
typedef unsigned short u16; //2B
typedef unsigned int u32; //4B int BytsPerSec; //Bytes of every sector
int SecPerClus; //sectors of a cluster
int RsvdSecCnt; //Boot记录占用的扇区数
int NumFATs; //FAT tables Num
int RootEntCnt; //max files Num of root directory
int FATSz; //num of FAT sectors #pragma pack (1) /*指定按1字节对齐*/ //offset is 11 bytes
struct BPB {
u16 BPB_BytsPerSec; //每扇区字节数
u8 BPB_SecPerClus; //每簇扇区数
u16 BPB_RsvdSecCnt; //Boot记录占用的扇区数
u8 BPB_NumFATs; //FAT表个数
u16 BPB_RootEntCnt; //根目录最大文件数
u16 BPB_TotSec16;
u8 BPB_Media;
u16 BPB_FATSz16; //FAT扇区数
u16 BPB_SecPerTrk;
u16 BPB_NumHeads;
u32 BPB_HiddSec;
u32 BPB_TotSec32; //如果BPB_FATSz16为0,该值为FAT扇区数
};
//BPB over,length is 25 bytes //root directory entry
struct RootEntry {
char DIR_Name[];
u8 DIR_Attr; //file attr
char reserved[];
u16 DIR_WrtTime;
u16 DIR_WrtDate;
u16 DIR_FstClus; //start cluster No
u32 DIR_FileSize;
};
//根目录条目结束,32字节
#pragma pack () /*取消指定对齐,恢复缺省对齐*/ struct subEntry {
char DIR_Name[];
u8 DIR_Attr;
char reserved[];
u16 DIR_WrTime;
u16 DIR_WrDate;
u16 DIR_FstClus;
u32 DIR_FileSize;
}; #pragma pack () /*取消指定对齐,恢复缺省对齐*/ void fillBPB(struct BPB* bpb_ptr); //载入BPB
void printFiles(struct RootEntry* rootEntry_ptr, Directory* rootnode); //打印文件名,这个函数在打印目录时会调用下面的printChildren
void printChildren(char * directory, int startClus,Directory * d); //打印目录及目录下子文件名
int getFATValue(int num); //读取num号FAT项所在的两个字节,并从这两个连续字节中取出FAT项的值,
void printFileContent(int startClus);
int getFATValue(int num); Directory root;
FILE* fat12; //global variable void init() {
struct BPB bpb;
struct BPB* bpb_ptr = &bpb; //载入BPB
fillBPB(bpb_ptr); //init all global variables
BytsPerSec = bpb_ptr->BPB_BytsPerSec;
SecPerClus = bpb_ptr->BPB_SecPerClus;
RsvdSecCnt = bpb_ptr->BPB_RsvdSecCnt;
NumFATs = bpb_ptr->BPB_NumFATs;
RootEntCnt = bpb_ptr->BPB_RootEntCnt;
if (bpb_ptr->BPB_FATSz16 != ) {
FATSz = bpb_ptr->BPB_FATSz16;
}
else {
FATSz = bpb_ptr->BPB_TotSec32;
} struct RootEntry rootEntry;
struct RootEntry* rootEntry_ptr = &rootEntry; //print in cursion
printFiles(rootEntry_ptr,&root);
}
//erase the spaces in the biginning and end
string& trim(std::string &s)
{
if (s.empty()) return s;
s.erase(, s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + );
return s;
} string ls_l_resolve(string command) {
const char * cmd1 = command.c_str();
int len = command.length(); //处理 -lll这种多个l的情况
int _l_beginIndex = ;
for (int i = ; i < len-; i++) {
if (cmd1[i] == '-'&&cmd1[i + ] == 'l') {
_l_beginIndex = i + ;
break;
}
}
int l_endIndex = _l_beginIndex;
for (int i = _l_beginIndex + ; i < len; i++) {
if (cmd1[i] != 'l') {
l_endIndex = i;
break;
}
}
if (_l_beginIndex != l_endIndex) {
command = command.substr(, _l_beginIndex+) + command.substr(l_endIndex,len-l_endIndex);
}
//cout << "comm:" << command << endl;
const char * cmd = command.c_str();
len = command.length(); int beginIndex = , endIndex = ;
int hasBegun = ; //是否已经进入目录的 beginIndex //form1:ls path -l
if (cmd[len - ] == 'l'&&cmd[len - ] == '-') {
for (int i = ; i < len; i++) {
if (cmd[i] != ' '&&!hasBegun) {
beginIndex = i;
hasBegun = ;
//break;
}
if (hasBegun && (cmd[i] == ' ' || cmd[i] == '-')) {
endIndex = i;
break;
}
}
}
else {
//form2:ls -l path
for (int i = ; i < len; i++) {
if (cmd[i] == '-'&&cmd[i + ] == 'l') {
beginIndex = i + ;
break;
}
}
for (int i = beginIndex+; i < len; i++) {
if (cmd[i] != ' ') {
beginIndex = i;
break;
}
}
endIndex = len;
}
string res = command.substr(beginIndex, endIndex - beginIndex);
return res;
}
//to upper
string upper(string s) {
string res;
const char* c = s.c_str();
for (int i = ; i < s.length(); i++) {
if (c[i] > &&c[i]<)res += (c[i] - );
else res += c[i];
}
return res;
}
//tranform path like '/a/b/c', return a vector
vector<string> getPathVector(string path) {
vector<string> pathVec;
const char* pathChars = path.c_str();
int len = path.length();
int beginIndex = ;
if (pathChars[] == '/')beginIndex++;
char temp[];//temp char arr
for (int i = beginIndex; i < len; i++) {
if (pathChars[i] == '/'||i==len-) {
pathVec.push_back(path.substr(beginIndex,(i==len-)?len:i-beginIndex));
beginIndex = i + ;
}
}
return pathVec;
} //得到路径中的目录
Directory locateDirectory(string path) {
path = upper(path);
vector<string> pathVector = getPathVector(path);
vector <Directory> dirArr; for (int i = ; i < pathVector.size(); i++) {
dirArr.push_back(getDirectory(root, pathVector[i]));
} Directory res = dirArr[dirArr.size() - ];
int isOK = ;
if(dirArr.size()==){
if(dirArr[].dirName.length()==)isOK=;
}
else{
for (int i = ; i < pathVector.size() - ; i++) {
if (!dirArr[i].hasSon(dirArr[i + ].dirName)) {
isOK = ;
break;
}
}
}
if (!isOK) res.dirNum = -; //如果路径不正确,将返回目录节点的dirName置-1
return res;
} void Main() {
string inp;
while ()
{
print(">",);
getline(cin, inp);
inp = trim(inp); const char* c_inp = inp.c_str(); int has_ = ;
for(int i =;i<inp.length();i++){
if(c_inp[i]=='-'){
has_ = ;
break;
}
} if (inp.compare("exit") == ) {
print( "Bye!\n",);
break;
}
if (inp.length() >= && c_inp[] == 'l'&&c_inp[] == 's') {
if (!inp.compare("ls")) {
ls_display(root);
}
else if(!inp.substr(,).compare("ls")&&!has_){
string path = inp.substr(,inp.length()-);
path = trim(path);
Directory dir = locateDirectory(path);
ls_display(dir);
}
else if(!inp.compare("ls -l")) {
ls_l_display(root);
}
else if(!inp.substr(,).compare("ls -L")) {
print("your command is invalid!\n",);
}
else {
string path = ls_l_resolve(inp);
//cout << "path: " << path << endl; if (path.length() == ) {
print("The path is invalid! Try again!\n",);
}
else {
Directory dir = locateDirectory(path);
if (dir.dirNum==-) {
print("The path is invalid! Try again!\n",);
}
else {
ls_l_display(dir);
}
}
}
}
else if (!inp.substr(,).compare("cat")) {
int i;
for (i = ; i < inp.length(); i++) {
if (c_inp[i] != ' ')break; //取出cat后面的space
}
//取出文件和目录:
int endIndex = inp.length() - ;
for (int i = endIndex; i >= ; i--) {
if (c_inp[i] == '/') {
endIndex = i;
break;
}
} string path = inp.substr(i, endIndex - i);
string fileName = inp.substr(endIndex + , inp.length() - endIndex - ); if (endIndex == inp.length() - ) {
path = "";
fileName = inp.substr(i, inp.length()-i);
}
//cout << "path: " << path << " file: " << fileName << endl;
Directory dir;
if (path.length() == ) { //path is empty, so it's root entry
dir = root;
}
else {
dir = locateDirectory(path);
}
if (dir.dirNum == -) {
print("The path is invalid!\n",);
}
else {
int cluster = dir.hasFile(upper(fileName));
if (cluster==-) {
print("The file is not exist!\n",);
}
else {
if (cluster >= )
printFileContent(cluster);
} }
}
else if(inp.length()>){
string s = "Wrong Command! Try Again!\n";
print(s,);
}
}
} void fillBPB( struct BPB* bpb_ptr) {
int check;
//BPB从偏移11个字节处开始
check = fseek(fat12, , SEEK_SET);
if (check == -)
print("fseek in fillBPB failed!\n",); //BPB长度为25字节
check = fread(bpb_ptr, , , fat12);
if (check != )
print("fread in fillBPB failed!\n",);
} void printFiles(struct RootEntry* rootEntry_ptr, Directory* root) {
int base = (RsvdSecCnt + NumFATs * FATSz) * BytsPerSec; //根目录首字节的偏移数
int check;
char realName[]; //暂存将空格替换成点后的文件名 //依次处理根目录中的各个条目
int i;
for (i = ; i < RootEntCnt; i++) { check = fseek(fat12, base, SEEK_SET);
if (check == -)
print("fseek in printFiles failed!\n",); check = fread(rootEntry_ptr, , , fat12);
if (check != )
print("fread in printFiles failed!\n",);
base += ;
if (rootEntry_ptr->DIR_Name[] == '\0') continue; //empty entry //filliter ilvalid
int j;
int boolean = ;
for (j = ; j < ; j++) {
if (!(((rootEntry_ptr->DIR_Name[j] >= ) && (rootEntry_ptr->DIR_Name[j] <= )) ||
((rootEntry_ptr->DIR_Name[j] >= ) && (rootEntry_ptr->DIR_Name[j] <= )) ||
((rootEntry_ptr->DIR_Name[j] >= ) && (rootEntry_ptr->DIR_Name[j] <= )) ||
(rootEntry_ptr->DIR_Name[j] == ' '))) {
boolean = ; //invalid char
break;
}
}
if (boolean == ) continue; //not object int k;
if ((rootEntry_ptr->DIR_Attr & 0x10) == ) {
//it's a file
int tempLong = -;
for (k = ; k < ; k++) {
if (rootEntry_ptr->DIR_Name[k] != ' ') {
tempLong++;
realName[tempLong] = rootEntry_ptr->DIR_Name[k];
}
else {
tempLong++;
realName[tempLong] = '.';
while (rootEntry_ptr->DIR_Name[k] == ' ') k++;
k--;
}
}
tempLong++;
realName[tempLong] = '\0'; //filename is realName root->addFile(realName,rootEntry_ptr->DIR_FileSize,rootEntry_ptr->DIR_FstClus);
//output fileName:
//printf("FileName: %s\n", realName);
}
else {
//it's a dir
int tempLong = -;
for (k = ; k < ; k++) {
if (rootEntry_ptr->DIR_Name[k] != ' ') {
tempLong++;
realName[tempLong] = rootEntry_ptr->DIR_Name[k];
}
else {
tempLong++;
realName[tempLong] = '\0';
break;
}
} //dir name is realName Directory d = Directory(realName);
root->addDir(d); //priint recurisively
printChildren(realName, rootEntry_ptr->DIR_FstClus, &root->subDirs[root->dirNum-]);
}
}
} void printChildren(char * directory, int startClus,Directory* d) {
//offset of No.2 cluster(the first cluster)
int dataBase = BytsPerSec * (RsvdSecCnt + FATSz * NumFATs + (RootEntCnt * + BytsPerSec - ) / BytsPerSec);
char fullName[]; //file /dir fullname
int strLength = strlen(directory);
strcpy(fullName, directory);
fullName[strLength] = '/';
strLength++;
fullName[strLength] = '\0';
char* fileName = &fullName[strLength]; int currentClus = startClus;
int value = ;
int ifOnlyDirectory = ; while (value < 0xFF8) { //value <FF8H
value = getFATValue(currentClus);
if (value < ) {
break;
}
if (value == 0xFF7) {
print("Bad cluster,failed!\n",);
break;
} char* str = (char*)malloc(SecPerClus*BytsPerSec); //暂存从簇中读出的数据
char* content = str; int startByte = dataBase + (currentClus - )*SecPerClus*BytsPerSec;
int check;
check = fseek(fat12, startByte, SEEK_SET);
if (check == -)
print("fseek in printChildren failed!\n",); check = fread(content, , SecPerClus*BytsPerSec, fat12);
if (check != SecPerClus * BytsPerSec)
print("fread in printChildren failed!\n",); //solve date of content,the regular entry structure is as same as root dir entry.
int count = SecPerClus * BytsPerSec; //bytes of a cluster
int loop = ;
while (loop < count) {
int i;
char tempName[]; //暂存替换空格为点后的文件名
if (content[loop] == '\0') {
loop += ;
continue;
} //empty entry //filiter the invaild things
int j;
int boolean = ;
for (j = loop; j < loop + ; j++) {
if (!(((content[j] >= ) && (content[j] <= )) ||
((content[j] >= ) && (content[j] <= )) ||
((content[j] >= ) && (content[j] <= )) ||
(content[j] == ' '))) {
boolean = ; //invaild char
break;
}
}
if (boolean == ) {
loop += ;
continue;
} //not object file if ((content[loop + ] & 0x10) == ) {
//File :
int k;
int tempLong = -;
for (k = ; k < ; k++) {
if (content[loop + k] != ' ') {
tempLong++;
tempName[tempLong] = content[loop + k];
}
else {
tempLong++;
tempName[tempLong] = '.';
while (content[loop + k] == ' ') k++;
k--;
}
}
tempLong++;
tempName[tempLong] = '\0'; int a = content[loop+],
b = content[loop + ],
c = content[loop + ],
d1 = content[loop + ];
a = a >= ? a : + a;//处理负数
b = b >= ? b: + b;
c = c >= ? c : + c;
d1 = d1 >= ? d1 : + d1; int size = a + *b + **c + ***d1; int x = content[loop + ];
int y = content[loop + ];
//cout << "cluster of : " << fullName<<"/"<<tempName<<" :" <<y * 256 + x << endl;
d->addFile(tempName,size, y * + x);
strcpy(fileName, tempName);
//printf("%s\n", fullName);
ifOnlyDirectory = ;
}
else {
//dir
int k;
int tempLong = -; for (k = ; k < ; k++) {
if (content[loop + k] != ' ') {
tempLong++;
tempName[tempLong] = content[loop + k];
}
else {
while (content[loop + k] == ' ') k++;
k--;
}
}
tempLong++;
tempName[tempLong] = '\0';
strcpy(fileName, tempName);
ifOnlyDirectory == ; Directory dir = Directory(tempName);
d->addDir(dir); int a = content[loop + ];
int b = content[loop + ];
printChildren(fullName, b*+a, &d->subDirs[d->dirNum-]);
}
loop += ;
}
free(str);
currentClus = value;
};
//if (ifOnlyDirectory == 0)
// printf("%s\n", fullName); //空目录的情况下,输出目录
} //输出文件内容:
void printFileContent(int startClus) {
int dataBase = BytsPerSec * (RsvdSecCnt + FATSz * NumFATs + (RootEntCnt * + BytsPerSec - ) / BytsPerSec);
int check;
int curclus = startClus;
int value = ;
while (value < 0xFF8) {//
value = getFATValue(curclus);
if (value < ) {
break;
}
if (value == 0xFF7) {
print( "bad cluster\n",);
}
char temp[];
int startByte = dataBase + * (curclus - );
check = fseek(fat12, startByte, SEEK_SET);
if (check == -)print( "Failed!\n",);
check = fread(temp, , , fat12);
temp[] = '\0';
print(temp,);
print("\n",);
curclus = value;
}
} int getFATValue(int num) {
int fatBase = RsvdSecCnt * BytsPerSec;
int fatPos = fatBase + num * / ;
int type = ;
if (num % == ) {
type = ; //even
}
else {
type = ; //odd
}
u16 bytes;
u16* bytes_ptr = &bytes;
int check;
check = fseek(fat12, fatPos, SEEK_SET);
if (check == -) {
print("fseek in getFATValue failed!\n",);
return -;
}
check = fread(bytes_ptr, , , fat12);
if (check != ) {
print("fread in getFATValue failed!\n",);
return -;
}
//u16为short,结合存储的小端顺序和FAT项结构可以得到
//type为0的话,取byte2的低4位和byte1构成的值,type为1的话,取byte2和byte1的高4位构成的值
if (type == ) {
bytes = bytes << ;
bytes = bytes >> ;
}
else {
bytes = bytes >> ;
}
return bytes;
} // Main, entrance of this program
int main() {
fat12 = fopen(IMG_PATH, "rb"); //open the fat12 image
init(); //init, build the file tree
Main(); //command solve and execute
fclose(fat12); //clost the file stream in the last。
return ;
}

NASM CODE:

my_print.asm

 global myPrint
;void myPrint(char *,int len,int color);
;color: -default, -red
;EdwinXu
section .data
color_default: db 1Bh, '[37;0m',
.length equ $ - color_default
color_red: db 1Bh, '[31;1m',
.length equ $ - color_red section .text myPrint:
mov eax, [esp+]
cmp eax,
je default_color ;set red
mov eax,
mov ebx,
mov ecx, color_red
mov edx, color_red.length
int 80h
jmp color_end
;set default color:
default_color:
mov eax,
mov ebx,
mov ecx, color_default
mov edx, color_default.length
int 80h ;print the str
color_end:
mov eax,
mov ebx,
mov ecx, [esp+] ;str
mov edx, [esp+] ;len
int 80h
;recover the color
mov eax,
mov ebx,
mov ecx, color_default
mov edx, color_default.length
int 80h ret

Makefile:

all:

ALL:
nasm -f elf32 my_print.asm
g++ -m32 my_print.o Main.cpp -o main
./main

FAT12 img tool的更多相关文章

  1. [免费了] SailingEase .NET Resources Tool (.NET 多语言资源编辑器)

    这是我2010年左右,写 Winform IDE (http://www.cnblogs.com/sheng_chao/p/4387249.html)项目时延伸出的一个小项目. 最初是以共享软件的形式 ...

  2. jBPM4.4 no jBPM DB schema: no JBPM4_EXECUTION table. Run the create.jbpm.schema target first in the install tool.

    jBPM4.4 no jBPM DB schema: no JBPM4_EXECUTION table. Run the create.jbpm.schema target first in the ...

  3. mtk flash tool,Win7 On VirtualBox

    SP_Flash_Tool_exe_Windows_v5.1624.00.000 Win7 在 VirtualBox, 安裝 mtk flash tool, v5.1628 在燒錄時會 fail. v ...

  4. 使用Microsoft Web Application Stress Tool对web进行压力测试

    Web压力测试是目前比较流行的话题,利用Web压力测试可以有效地测试一些Web服务器的运行状态和响应时间等等,对于Web服务器的承受力测试是个非常好的手法.Web 压力测试通常是利用一些工具,例如微软 ...

  5. How to Use Android ADB Command Line Tool

    Android Debug Bridge (adb) is a tool that lets you manage the state of an emulator instance or Andro ...

  6. 使用MAT(Memory Analyzer Tool)工具分析dump文件--转

    原文地址:http://gao-xianglong.iteye.com/blog/2173140?utm_source=tuicool&utm_medium=referral 前言 生产环境中 ...

  7. Linux Cmd Tool 系列之—script & scriptreplay

    Intro Sometime we want to record cmd and outputs in the interactive shell sessions. However history ...

  8. [Tool] SourceTree操作中遇到错误(Filename too long)的解决方案

    [Tool] SourceTree操作中遇到错误(Filename too long)的解决方案 问题情景 使用SourceTree,可以方便开发人员使用图形化接口的Git指令来管理原始码.但是在Wi ...

  9. You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1

    今天在Windows Server 2008 下安装SQL SERVER 2008时,碰到如下错误: You must use the Role Management Tool to install ...

随机推荐

  1. 条形码(barcode)code128生成代码

    条形码(barcode)code128生成代码 很简单 多些这位兄弟https://bbs.csdn.net/topics/350125614 下面是我的DEMO 直接放到VS2005下面编译即可 # ...

  2. GUID和UUID、CLSID、IID 区别及联系

    当初微软设计com规范的时候,有两种选择来保证用户的设计的com组件可以全球唯一: 第一种是采用和Internet地址一样的管理方式,成立一个管理机构,用户如果想开发一个COM组件的时候需要向该机构提 ...

  3. ping: sendto: No route to host

    root@tuhooo:/home/ # ping www.baidu.comPING www.a.shifen.com (61.135.169.125): 56 data bytesping: se ...

  4. 读取yaml中的内容

    def read_yml(path): """ 读取yml文件中的数据 :param path: 文件yaml 的路径 :return: 返回读取yaml文件内的结果 & ...

  5. Android下Native的so编译:使用ndk-build.cmd/.sh

    最近将一个DLL库移植至安卓下,编译出so文件. 经历makefile.cmake等等的入门到放弃..... 最后还是使用android的ndk编译命令来解决 每个NDK文件下,均包含的是所有工具链. ...

  6. Java——ArrayList源码解析

    以下针对JDK 1.8版本中的ArrayList进行分析. 概述     ArrayList基于List接口实现的大小可变的数组.其实现了所有可选的List操作,并且元素允许为任意类型,包括null元 ...

  7. xmake从入门到精通10:多个子工程目标的依赖配置

    xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验. 本文主要详细讲解下,如果在一个项目中维护和生成多个 ...

  8. oracle表名中带@什么意思

    例如:select * from dim.dim_area_no@to_dw @后是实例名或数据源,一个简单例子,服务器上创建了2个数据库实例,名称分别为HR.BOSS, 如果你用PL/SQL DEV ...

  9. centos7里创建用户和组

    1.创建组distro,其GID为2019groupadd -g 2019 distro 2.创建用户mandriva, 其ID号为1005:基本组为distro useradd mandriva - ...

  10. Spark-Core RDD行动算子

    1.reduce(func) 通过func函数聚集RDD 中的所有元素,先聚合分区内数据,再聚合分区间数据. scala> val rdd1 = sc.parallelize(1 to 100) ...