作业要求在xv6操作系统里面增加一个新的system call,这个system call要将程序执行过程中所有执行过的system call记录下来,以及与kernel进行交互的次数。但一开始对C语言不熟悉(不知道可以通过head file或extent来共享数据),所以只想到每次调用system call的时候进行读写操作,将结果写进txt文本,然后新的system call只负责读取文件。这个最终没有实现。第一,读写本身属于system call,会整的很混乱;第二,没法记录与kernel交互的情况;第三,system call文件太多,而且位置不在一起。。。
虽然做了无用功,但总归顺便学习了C语言,应该记录下来。
总体思路是这样的。
1. 首先txt文档的格式应该确定下来。它应该包含以下数据:a)第一行放system call的种类的个数,或者说行数;b)第二行第一个位置放system call字符串的长度;c)第二行第二个位置放system call的名字;d)第二行第三位置放该system call执行了几次...
如下:
4
8 command1 1
8 command2 2
8 command3 1
8 command4 1
这样做的目的是为了以后malloc方便一点。
2. 无论读写,首先要准备一个FILE型指针变量,它控制文件的开关以及是可以执行什么操作(fd),就好像是文件和用户交互的中转站。例如 FILE *pointer = fopen("1.txt", "r");表示用pointer来联系到1.txt,并执行读操作。但注意,如果文件不存在,pointer为NULL,不能使用fclose(pointer); 命令,否则报错。但FILE *pointer = fopen("1.txt", "w");的话没关系,因为“w”操作即使没有文件,也会创造一个新文件,保证了pointer不为NULL,因此程序后期必须用到fclose(pointer);。还有写文件的时候,比如1.txt,一定写明白”.“后面文件类型。
3. 读操作:fscanf(pointer, “%i %s”, num, string);表示将pointer(pointer对应的必然是“r”操作)所对应的文件里面的两个物品(必然是整数和字符串),放到早已定义好的num和string变量里面去。之所以是两个物品是因为他们之间用空格或回分隔。
4. 写操作:fprintf(pointer, “%i %s\n”, num, string);表示将两个物品(必然是整数和字符串)放到pointer(pointer对应的必然是“w”操作)所对应的文件里面去。注意“%i %s\n”已经将两个物品用空格加以区分,而且还换行,但是读操作的时候不管回车还是空格都直接跳过。
5. 关闭文件:fclose(pointer);pointer不能为NULL。
6. 删除文件:remove(”1.txt“);
7. 重命名:rename("1.txt", "2.txt");
#include
#include
#include
//建立结构体,包含一个字符型指针变量,以及一个整数。
typedef struct
{
char *commandName;
int commandNumber;
}commandInfo;
void updateFile(char *inputCommandName)
{
//开两个文件一个新一个旧。
FILE *origionalFile = fopen("record.txt", "r");
FILE *newFile = fopen("newRecord.txt", "w");
//”record.txt“被删除了,或没被建立,在新文件写入上述格式的数据。
if (origionalFile == NULL)
{
fprintf(newFile, "%i\n", 1);
fprintf(newFile, "%i %s %i", strlen(inputCommandName), inputCommandName, 1);
}
//”record.txt“里面有东西,就将他们提取出来放到结构体里面,注意提取的过程中如果发现经要写入的
//system call信息原文件里有,那就在后面加一。
else
{
int totalNumber;
fscanf(origionalFile, "%i", &totalNumber);
//根据最开始的system call种类数,为结构体开辟足够空间。
commandInfo *info = (commandInfo*) malloc(sizeof(commandInfo) * (totalNumber));
//设一个旗帜,如果原文件的内容全部写到结构体后,没法发现新system call,就在新文件最后头
//加上它
int isRepeated = 0;
//根据开头行数,将每行内容保存到结构体里面。
for (int i = 0; i < totalNumber; i++)
{
int nameLen;
fscanf(origionalFile, "%i", &nameLen);
//每行前头的system call长短,就是为了malloc的。
char *tempName = (char *) malloc(sizeof(char) * (nameLen + 1));
//string最后需要以‘\0’结尾。
tempName[nameLen] = '\0';
int tempNum;
fscanf(origionalFile, "%s %i", tempName, &tempNum);
//比较下原文件里面有没有本次的system call,有就设置旗帜,顺便加一。
if (strcmp(tempName, inputCommandName) == 0)
{
isRepeated = 1;
tempNum++;
}
info[i].commandName = tempName;
info[i].commandNumber = tempNum;
//结构体还不是很理解,似乎结构体里面保存的是指针,因此这里free的话会导致数据丢失。
//free(tempName);
}
//system call是不新元素,直接从结构体取出信息写到新文件里。
if (isRepeated == 1)
{
fprintf(newFile, "%i\n", totalNumber);
for (int i = 0; i < totalNumber; i++)
fprintf(newFile, "%i %s %i\n", strlen(info[i].commandName), info[i].commandName, info[i].commandNumber);
}
//新system call,行数要首先加一,结构体写完以后,在把新system call信息写到最后面。
else
{
fprintf(newFile, "%i\n", totalNumber + 1);
for (int i = 0; i < totalNumber; i++)
fprintf(newFile, "%i %s %i\n", strlen(info[i].commandName), info[i].commandName, info[i].commandNumber);
fprintf(newFile, "%i %s %i\n", strlen(inputCommandName), inputCommandName, 1);
}
//结构体没用了,把它释放。但是前面在heap里开辟的那些Name还没有释放,回头改一下。
free(info);
//关掉老文件。
fclose(origionalFile);
}
fclose(newFile);
remove("record.txt");
rename("newRecord.txt", "record.txt");
}
//读文件,显示在屏幕上。每次执行完以后删除txt文件。
void readFile()
{
FILE *file = fopen("record.txt", "r");
if (file == NULL)
{
printf("No system call!");
return;
}
else
{
int totalNum;
fscanf(file, "%i", &totalNum);
printf("System call type: %d\n", totalNum);
for (int i = 0; i < totalNum; i++)
{
int length;
fscanf(file, "%i", &length);
char *tempName = (char *) malloc(sizeof(char)*(length+1));
tempName[length] = '\0';
int tempNum;
fscanf(file, "%s %i", tempName, &tempNum);
printf("System call name: %s times: %d\n", tempName, tempNum);
}
fclose(file);
}
remove("record.txt");
}
int main()
{
char temp1[10] = "command1";
updateFile(temp1);
char temp2[10] = "command2";
updateFile(temp2);
char temp3[10] = "command3";
updateFile(temp3);
char temp4[10] = "command4";
updateFile(temp4);
char temp5[10] = "command2";
updateFile(temp5);
readFile();
return 0;
}
执行后的结果:
System call type: 4
System call name: command1 times: 1
System call name: command2 times: 2
System call name: command3 times: 1
System call name: command4 times: 1