先安装ccache可以大幅节省多次内核编译时间
vim ./arch/x86/entry/syscalls/syscall_64.tbl
尾部添加 ([549]为最后一个系统调用号+1)
549 64 mysetnice sys_mysetnice
vim ./include/linux/syscalls.h
asmlinkage long sys_mysetnice(pid_t pid,int flag,int nicevalue); //,void __user* prio,void __user* nice);
vim ./kernel/sys.c
SYSCALL_DEFINE3(mysetnice, pid_t, pid, int, flag, int, nicevalue)
{
struct pid * kpid;
struct task_struct * task;
int nicebef;
kpid = find_get_pid(pid);/* 返回pid */
task = pid_task(kpid, PIDTYPE_PID);/* 返回task_struct */
nicebef = task_nice(task);/* 返回进程当前nice值 */
if(flag == 1)
{
set_user_nice(task, nicevalue);/* 修改进程nice值 */
printk("修改前nice值:%d\t修改后nice值:%d\n", nicebef, nicevalue);
return 0;
}
else if(flag == 0)
{
printk("该进程的nice值为%d\n", nicebef);
return 0;
}
return EFAULT;
}
make oldconfig
make
make modules
make modules_install
make install
grub2-mkconfig -o /boot/grub2/grub.cfg //centos
update-grub2 //ubuntu
reboot
#include
#include
#include
#include
#define __NR_mysetnice 549
int main(int argc, char *argv[])
{
pid_t tid;
int nicevalue = atoi(argv[1]);
tid = getpid();
syscall(__NR_mysetnice,tid,0,0);
syscall(__NR_mysetnice,tid,1,nicevalue);
syscall(__NR_mysetnice,tid,0,0);
//syscall(__NR_mysetnice,tid,flag,nicevalue);
return 0;
}
dmesg
Makefile的KDIR需要修改为内核目录 Makefile 和 OS-2-x.c在同一文件夹内即可 执行make编译
obj-m:=OS-2-1.o
OS21-objs:=OS-2-1.o
KDIR:=/home/kannaduki/linux/linux-4.15.15
PWD:= $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
#include
#include
#include
// 内核版本为3.X 则为
#include
static int hello_init(void)
{
struct task_struct *p= &init_task;
printk(KERN_ALERT"\n\n\n----------------------");
printk(KERN_ALERT"------所有进程程序名 pid 进程状态 父进程------");
for_each_process(p) {
if(p->mm == NULL)
printk(KERN_ALERT"程序名: %s Pid: %d 进程状态: %ld 父进程pid: %d\n",p->comm,p->pid, p->state,p->real_parent->pid);
}
printk(KERN_ALERT"----------------------\n\n\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "______Exit______ !\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
obj-m:=OS-2-2.o
OS22-objs:=OS-2-2.o
KDIR:=/home/kannaduki/linux/linux-4.15.15
PWD:= $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
#include
#include
#include
#include
// 内核版本为3.X 则为
#include
#include
static pid_t pid=0;
module_param(pid,int,0644);
static int family_init(void)
{
struct task_struct *p;
struct list_head *pp;
struct task_struct *pl;
if(pid == 0) {
printk("输入错误\n");
return 0;
}
p = pid_task(find_vpid(pid), PIDTYPE_PID);
if(!p) {
printk("\n\n\n------进程不存在----\n\n\n");
return 0;
}
printk("\n\n\n\n\n\n\n\n\n");
printk("-----进程号------\n");
printk("%d\n",pid);
printk("-----父进程------\n");
if(p->parent==NULL)
{
printk("父进程不存在\n");
}
else
{
printk("pid: %d 程序名:%s 进程状态: %ld\n",p->parent->pid,p->parent->comm,p->parent->state);
}
printk("------兄弟进程-------\n");
list_for_each(pp,&p->parent->children)
{
pl=list_entry(pp,struct task_struct,sibling);
printk("pid: %d 程序名: %s 进程状态: %ld\n",pl->pid,pl->comm,pl->state);
}
printk("---------子进程--------\n");
if(&p->children==NULL) printk("子进程不存在");
list_for_each(pp,&p->children)
{
pl=list_entry(pp,struct task_struct,sibling);
printk("pid: %d 程序名: %s 进程状态: %ld\n",pl->pid,pl->comm,pl->state);
}
printk("-----------------------\n\n\n\n\n\n");
return 0;
}
static void family_exit(void)
{
printk(KERN_ALERT "\n--------Exit---------\n");
}
module_init(family_init);
module_exit(family_exit);
MODULE_LICENSE("GPL");
#include
void main() {
printf("cmd1运行完毕\n");
}
gcc cmd1.c -o cmd1 (cmd2 cmd3 同理)
#include
#include
#include
#include
void main() {
int pid;
int i;
char *cmd = (char*)malloc(sizeof(20));
while(1) {
printf("输入指令\n");
scanf("%s",cmd);
if(strcmp(cmd,"exit")==0) return;
pid=vfork();
if (pid) {
waitpid(pid,NULL,0);
}else{
if(strcmp(cmd,"cmd1")==0 || strcmp(cmd,"cmd2")==0 || strcmp(cmd,"cmd3")==0){
execl(cmd,cmd,NULL);
}else{
printf("Command not found\n");
_exit(0);
}
}
}
}
gcc shell.c
#include
#include
#include
#include
#include
int main()
{
int filedes[2];
pid_t child1;
pid_t child2;
pid_t child3;
char b_read[100]={0};
int num;
sem_t sem;
sem_init(&sem,1,1);
//int pipe(int filedes[2])
if(pipe(filedes)<0)
exit(-1);
else {
//close(filedes[0]);
//close(filedes[1]);
}
//filedes[0]读 filedes[1]写
pid_t p1 = fork();
if(p1==0) {
sem_wait(&sem);
close(filedes[0]);
open(filedes[1]);
write(filedes[1],"1111",4);
printf("child1 写入 写入值为1111\n\n");
close(filedes[1]);
sem_post(&sem);
exit(0);
}
pid_t p2 = fork();
if(p2==0) {
sem_wait(&sem);
close(filedes[0]);
open(filedes[1]);
write(filedes[1],"2222",4);
printf("child2 写入 写入值为2222\n\n");
close(filedes[1]);
sem_post(&sem);
exit(0);
}
pid_t p3 = fork();
if(p3==0) {
sem_wait(&sem);
close(filedes[0]);
open(filedes[1]);
write(filedes[1],"3333",4);
printf("child3 写入 写入值为3333\n\n");
close(filedes[1]);
sem_post(&sem);
exit(0);
}
int s1,s2,s3,n;
//open(filedes[0]);
close(filedes[1]);
//waitpid(p1,&s1,0);
//waitpid(p2,&s2,0);
//waitpid(p3,&s3,0);
usleep(400);
printf("请输入读取数\n");
scanf("%d",&n);
printf("读取%d\n\n",n);
num = read(filedes[0],b_read,n);
printf("返回值%d,读取值%s\n\n",num,b_read);
close(filedes[0]);
return 0;
}
gcc OS-3-2.c -o OS-3-2 -pthread
#include
#include
#include
#include
#include
#include
#include
#include
// gcc OS-3-3.c -o OS-3-3 -pthread
// ./OS-3-3
// 第三个题和第四个题跑多了好像ftok的key_t会混起来 接收不到信息 改一下或者重启一下就行了
sem_t sem;
int sval;
void sender() {
sem_wait(&sem);
key_t key;
int msqid,msnd;
char msgp[100] = {0};
key = ftok(".",1);
msqid = msgget(key,IPC_CREAT);
while(1) {
printf("请输入消息\n");
scanf("%s",msgp);
if(strcmp(msgp,"exit")==0){
strcpy(msgp,"end");
msnd = msgsnd(msqid,msgp,strlen(msgp),MSG_NOERROR);
printf("--------------------------------\n");
printf("发送%d个字符(end),应答信息如下\n",strlen(msgp));
break;
}else{
msnd = msgsnd(msqid,msgp,strlen(msgp),MSG_NOERROR);
printf("发送%d个字符,输入exit应答\n",strlen(msgp));
}
}
//msnd = msgsnd(msqid,msgp,strlen(msgp),MSG_NOERROR);
//printf("sender key_t: %d IPC:%d \n",key,msqid);
sem_post(&sem);
usleep(100);
sem_wait(&sem);
msgrcv(msqid,msgp,100,0,0);
printf("sender 接收 %s\n",msgp);
sem_post(&sem);
}
void receiver() {
usleep(100);
sem_wait(&sem);
//printf("receiver start\n");
key_t key;
int msqid;
int count;
ssize_t mrcv;
struct msqid_ds *buf;
char msgp[100]={0};
key = ftok(".",1);
msqid = msgget(key,IPC_CREAT);
count = 0;
while(msgrcv(msqid,msgp,100,0,IPC_NOWAIT)!= -1) {
count++;
printf("第%d条信息 %s\n",count,msgp);
}
strcpy(msgp,"over");
msgsnd(msqid,msgp,strlen(msgp),MSG_NOERROR);
printf("receiver 发送 over\n");
sem_post(&sem);
usleep(100);
if(msgctl(msqid,IPC_RMID,buf) == 0)
printf("消息队列删除成功\n");
printf("-----------------------------\n");
}
int main(void)
{
pthread_t tid1, tid2;
sem_init(&sem, 0, 1);
pthread_create(&tid1,NULL,sender,NULL);
pthread_create(&tid2,NULL,receiver, NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
sem_destroy(&sem);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct shm_msg {
pid_t pid;
char msg[100];
};
int main() {
sem_t *sem;
int shmid;
char msg[100];
struct shm_msg *shmaddr;
sem = sem_open("mysem",O_CREAT,0644,1);
shmid = shmget(ftok(".",1),1024,IPC_CREAT);
shmaddr = shmat(shmid,0,0);
shmaddr->pid = -1;
printf("请输入字符串\n");
scanf("%s",msg);
sem_wait(sem);
shmaddr->pid = 1;
strcpy(shmaddr->msg,msg);
printf("sender 发送 %s\n",shmaddr->msg);
sem_post(sem);
while(1) {
if(shmaddr->pid == 0){
sem_wait(sem);
printf("sender 接收 %s",shmaddr->msg);
break;
}
}
sem_post(sem);
sem_close(sem);
sem_unlink("mysem");
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct shm_msg {
pid_t pid;
char msg[100];
};
int main()
{
sem_t *sem;
int shmid;
char msg[100];
struct shm_msg *shmaddr;
sem = sem_open("mysem",O_CREAT,0644,1);
shmid = shmget(ftok(".",1),1024,IPC_CREAT);
shmaddr = shmat(shmid,0,0);
while(1) {
if(shmaddr->pid == 1){
sem_wait(sem);
printf("receiver 接收 %s\n",shmaddr->msg);
strcpy(shmaddr->msg,"over");
printf("receiver 发送 %s \n",shmaddr->msg);
shmaddr->pid = 0;
break;
}
}
sem_post(sem);
sem_close(sem);
return 0;
}
打开两个终端 一个执行sender 一个执行receiver sender发送信息后receiver会接收
#include
#include
#include
#include
#define BLOCKSIZE 1024
#define SIZE 1024000
#define END 65535
#define FREE 0
#define MAXOPENFILE 10
#define CUVER 0
#define APPEND 1
#pragma warning(disable:4996)
typedef struct BLOCK0 {
char infomation[50]; //你想要提示的第一句话
unsigned short blocksize; //设成1024,单位B
unsigned short totalsize; //设成1000,单位KB
unsigned short fat_num; // fat表的数量,设成2
unsigned short root;// 根目录文件的起始盘块号
unsigned char *startblock;
/*tsz:对free的管理需要完善*/
unsigned free_block; //剩余未使用的块数
}block0;
typedef struct FCB {
char filename[8]; //文件名
char exname[3]; //扩展名
unsigned char attribute; //属性,0目录;1文件
unsigned short time;
unsigned short data;
unsigned short first;
unsigned long length;
char free; //0为空,1相反
char reserved[7]; //预留,同时也为了内存对齐
}fcb;
// /* 这个数据结构为长文件准备,以倒序顺序放在长文件FCB的前面*/
//typedef struct EXTEND_NAME{
// unsigned char endflag; /*若end是1则为最后一个EXTEND_NAME,否则为0*/
// char extname1[10]; /*扩展名的存储位置1*/
// unsigned char attribute; /*属性,长文件的扩展名的属性为4*/
// char extname2[20]; /*扩展名的存储位置2*/
//}ext_name;
typedef struct FAT {
unsigned short id;
}fat;
typedef struct USEROPEN {
char filename[8];
char exname[4];
unsigned char attribute;
unsigned short time;
unsigned short data;
unsigned short first;
unsigned long length;
char free;
fcb *ptrfcb; //指向加载的fcb
int count; //读写指针的位置
short fcbstate;// 是否修改了文件的FCB的内容,1:修改;0:未修改
short topenfile;// 户打开表项是否为空,0:空;1:已分配
}useropen;
unsigned char *myvhard; //虚拟磁盘开始位置的指针
useropen openfilelist[MAXOPENFILE];
char currentdir[100];
unsigned char* startp; //磁盘数据区开始位置的指针
useropen *ptrcurdir;// 指向用户打开文件表中的当前目录所在打开文件表项的位置
fat *fat1;
fat *fat2;
void info() {
block0 *p = (block0*)myvhard;
printf("*\t%s\n", p->infomation);
printf("*\t块大小为:%dB,总大小为:%dKB\n", p->blocksize, p->totalsize);
printf("*\tfat表数量为:%d\n", p->fat_num);
printf("*\t数据区的开始块数为:%d\n", p->root);
printf("*\t剩余未分配块数为:%d\n", p->free_block);
}
void help() {
printf("*\t命令名称\t参数\t\t解释\n");
printf("*\tinfo\t\t无\t\t获取文件系统整体信息\n");
printf("*\thelp\t\t无\t\t获取所有命令的说明\n");
printf("*\tcd\t\tdirname\t\t改变当前目录到指定的名为 dirname 的目录\n");
printf("*\topen\t\tfilename\t打开当前目录下名为 filename 的文件\n");
printf("*\tformat\t\t无\t\t对虚拟磁盘进行格式化,布局虚拟磁盘,建立根目录文件(或根目录区)\n");
printf("*\tmkdir\t\tdirname\t\t在当前目录下创建名为 dirname 的子目录\n");
printf("*\trmdir\t\tdirname\t\t在当前目录下删除名为 dirname 的子目录\n");
printf("*\tls\t\t无\t\t显示当前目录的内容(子目录和文件信息)\n");
printf("*\tcreate\t\tfilename\t创建名为 filename 的新文件\n");
printf("*\tclose\t\tfd\t\t关闭前面由 my_open 打开的文件描述符为 fd 的文件\n");
printf("*\twrite\t\tfd\t\t将接下来输入的文本保存到前面由 my_open 打开的文件描述符为 fd 的文件\n");
printf("*\tread\t\tfd\t\t将前面由 my_open 打开的文件描述符为 fd 的文件中读取 1024 个字节的文本\n");
printf("*\trm\t\tfilename\t删除名为 filename 的文件\n");
printf("*\texit\t\t无\t\t退出文件系统\n");
printf("*\tshow\t\t无\t\t显示所有已打开文件的fd值\n");
}
void fcbcpy(int i, fcb *fileFcb) {
strcpy(openfilelist[i].filename, fileFcb->filename);
strcpy(openfilelist[i].exname, fileFcb->exname);
openfilelist[i].attribute = fileFcb->attribute;
openfilelist[i].time = fileFcb->time;
openfilelist[i].data = fileFcb->data;
openfilelist[i].first = fileFcb->first;
openfilelist[i].length = fileFcb->length;
openfilelist[i].free = fileFcb->free;
openfilelist[i].ptrfcb = fileFcb;
openfilelist[i].fcbstate = 0;
openfilelist[i].topenfile = 1;
openfilelist[i].count = 0;
}
void init_fat1() {
fat *p = (fat*)(myvhard + BLOCKSIZE);
fat *p1, *p2;
p1 = p2 = p;
int i;
for (i = 0; i<2 * BLOCKSIZE / sizeof(fat); ++i, ++p1)(p1->id) = FREE;
for (i = 0; i<7; ++i, ++p2)p2->id = END;
p[5].id = 6;
fat1 = (fat*)(myvhard + BLOCKSIZE);
fat2 = (fat*)(myvhard + 3 * BLOCKSIZE);
}
void init_b0() {
block0 *p_b0 = (block0*)myvhard;
strcpy(p_b0->infomation, "File System made by 陈王杰 汤胜中 徐时越 包治宽");
p_b0->blocksize = BLOCKSIZE;
p_b0->totalsize = SIZE / 1024;
p_b0->fat_num = 2;
p_b0->root = 5;
p_b0->startblock = myvhard + 5 * BLOCKSIZE;
p_b0->free_block = (SIZE / BLOCKSIZE) - 6;
}
void bak_fat1() {
memcpy(myvhard + 3 * BLOCKSIZE, myvhard + BLOCKSIZE, 2 * BLOCKSIZE);
}
void get_time(int *data_time) {
time_t now;
time(&now);
struct tm *nowtime;
nowtime = localtime(&now);
data_time[1] = nowtime->tm_hour * 2048 + nowtime->tm_min * 32 + nowtime->tm_sec / 2; /*前面的两个乘是为了移位*/
data_time[0] = (nowtime->tm_year - 80) * 512 + (nowtime->tm_mon + 1) * 32 + nowtime->tm_mday;
}
void check_enough_block(int block_index,int blocknum_need) {
fat temp=fat1[block_index];
int i,j;
for (i = 0; i < blocknum_need; ++i) {
if (temp.id == END)break;
if(i!=blocknum_need-1){
int need_new = blocknum_need - i - 1;
for (j = 0; j < need_new; ++j)temp.id = dirst_block();
temp = fat1[temp.id];
temp.id = END;
}
}
}
void clean_openfilelist(int index) {
strcpy(openfilelist[index].filename, "\0");
strcpy(openfilelist[index].exname, "\0");
openfilelist[index].attribute = 0;
openfilelist[index].time = 0;
openfilelist[index].data = 0;
openfilelist[index].first = 0;
openfilelist[index].length = 0;
openfilelist[index].fcbstate = 0;
openfilelist[index].ptrfcb = NULL;
openfilelist[index].free = 0;
openfilelist[index].topenfile = 0;
openfilelist[index].count = 0;
}
int is_rootdir(fcb *fileFcb) {
if (fileFcb->first == 5)return 1;
else return 0;
}
int getblocknum_fromfilelen(int len) {
if (len == 0)return 1;
else return len % BLOCKSIZE == 0 ? (len / BLOCKSIZE) : (len / BLOCKSIZE + 1);
}
fcb* exist_file(fcb *fileFcb,char* filename) {
int length = fileFcb->length;
int flag = 0;
int i;
for (i = 0; i < length / sizeof(fcb); i++, ++fileFcb) {
if (!strcmp(fileFcb->filename, filename)) {
flag = 1;
break;
}
if (fileFcb->free == 0)
i--;
}
if (flag == 0)return NULL;
else return fileFcb;
}
/*创建新文件夹时,传入为为新文件夹分配的块号即可快速完成新文件目录下的.和..的创建*/
/*root参数一般传0就好*/
void fast_dir(int dirst_block, int root) {
char* block_start = (char*)myvhard + dirst_block * BLOCKSIZE;
fcb* p = (fcb*)block_start;
int i;
for (i = 0; ifree = 0;
fcb *cur = (fcb*)block_start;
fcb *father = (cur + 1);
int data_time[2];
get_time(data_time);
strcpy(cur->filename, ".");
strcpy(father->filename, "..");
strcpy(cur->exname, "di");
strcpy(father->exname, "di");
cur->attribute = father->attribute = 0;
cur->time = father->time = data_time[1];
cur->data = father->data = data_time[0];
cur->first = dirst_block;
cur->length = 2 * sizeof(fcb);
if (root) {
father->first = cur->first;
father->length = cur->length;
}
else {
i = get_curnum();
father->first = openfilelist[i].first;
father->length = openfilelist[i].length;
}
cur->free = father->free = 1;
fat1[dirst_block].id = END;
fat2[dirst_block].id = END;
}
void fast_dirfcb(fcb *fileFcb, char *dirname,int dirst_block) {
strcpy(fileFcb->filename, dirname);
strcpy(fileFcb->exname, "di");
fileFcb->attribute = 0;
int time[2];
get_time(time);
fileFcb->time = time[1];
fileFcb->data = time[0];
fileFcb->first = dirst_block;
fileFcb->free = 1;
fileFcb->length = 2 * sizeof(fcb);
}
/* fat的前5个给了block0,fat1,fat2*/
void my_format() {
init_b0();
init_fat1();
bak_fat1();
fast_dir(5, 1);
}
void startsys() {
myvhard = (unsigned char*)malloc(SIZE);
memset(myvhard, 0, SIZE);
FILE * fp;
if ((fp = fopen("./my_fs", "r")) != NULL) {
fread(myvhard, SIZE, 1, fp);
fclose(fp);
}
else {
printf("*\tfile not found!new file created!\n");
my_format();
}
fcbcpy(0, (fcb*)(myvhard + 5 * BLOCKSIZE));
ptrcurdir = &openfilelist[0];
/*初始化后面的所有opoenfilelist项*/
int i;
for (i = 1; i < MAXOPENFILE; i++) {
clean_openfilelist(i);
}
/*设置一些全局变量*/
strcpy(currentdir, "/");
startp = ((block0 *)myvhard)->startblock;
fat1 = (fat*)(myvhard + BLOCKSIZE);
fat2 = (fat*)(myvhard + 3 * BLOCKSIZE);
}
int get_curnum() {
return(ptrcurdir - openfilelist);
}
int dirst_block() {
int i, freeBlock;
fat *fat1 = (fat *)(myvhard + BLOCKSIZE);
fat *fat2 = (fat *)(myvhard + BLOCKSIZE * 3);
int flag = 0;
for (i = 0; i < BLOCKSIZE * 2 / sizeof(fat); i++) {
if (fat1->id == FREE) {
flag = 1;
freeBlock = i;
return i;
}
fat1++;
fat2++;
}
if (flag == 0) {
printf("FAT满了!");
return -1;
}
}
int get_block_num(int start_block) {
int i = 1;
fat *fat1 = (fat*)(myvhard + BLOCKSIZE);
fat *fat_t = fat1 + start_block;
if (fat_t->id == FREE)return 0;
else {
while (fat_t->id != END) {
++i;
fat_t = fat1 + fat_t->id;
}
}
return i;
}
void fast_file(fcb*fileFcb, char *filename, int dirstblock) {
strcpy(fileFcb->filename, filename);
strcpy(fileFcb->exname, "txt");
fileFcb->attribute = 1;
int time[2];
get_time(time);
fileFcb->time = time[1];
fileFcb->data = time[0];
fileFcb->first = dirstblock;
fileFcb->free = 1;
fileFcb->length = 0;
fat *fat1 = (fat*)(myvhard + BLOCKSIZE);
fat *fat2 = (fat*)(myvhard + 3*BLOCKSIZE);
fat1[dirstblock].id = END;
fat2[dirstblock].id = END;
}
void update_dir(char *filename) {
if (strcmp(filename, ".") && strcmp(filename, "..")) {
if (!strcmp(currentdir, "/"))strcat(currentdir, filename);
else {
strcat(currentdir, "/");
strcat(currentdir, filename);
}
}
}
void update_dir_father() {
int last = findlast();
currentdir[last] = '\0';
}
int findlast() {
int i, j;
i = j = 0;
while (currentdir[i] != '\0') {
if (currentdir[i] == '/')j = i;
++i;
}
if (j == 0)++j;
return j;
}
void my_ls() {
printf("filename\texname\t\ttime\t\tdata\t\tsize\n");
/*找到当前目录再openfilelist中得位置*/
int i = get_curnum();
// 读取当前目录文件的内容到内存
char *buf = (char *)malloc(1024);
do_read(i, 1024, buf);
fcb *fileFcb = (fcb *)buf;
int num = fileFcb->length / sizeof(fcb);
for (i = 0; i < num; i++, fileFcb++) { /*只有fileFCB是真的文件(目录),i才会增加*/
if (fileFcb->free == 1) {
char exname[4];
int j;
for (j = 0; j<3; ++j)exname[j] = fileFcb->exname[j];
exname[3] = '\0';
printf("%s\t\t%s\t\t%02d:%02d:%02d\t%02d,%02d,%02d\t%d\n", fileFcb->filename, exname, fileFcb->time / 2048, (fileFcb->time % 2048) / 32, (fileFcb->time % 32) * 2, fileFcb->data / 512 + 1980, fileFcb->data % 512 / 32,
fileFcb->data % 32, fileFcb->length);
}
else i--;
}
free(buf);
}
void my_mkdir(char *dirname) {
int i = get_curnum();
int curOpenNum = i;
char *buf = (char *)malloc(1024);
do_read(i, 1024, buf);
fcb *fileFcb = (fcb *)buf;
int fcb_num = fileFcb->length / sizeof(fcb);
for (i = 0; i < fcb_num; ++i, ++fileFcb) {
if (!strcmp(fileFcb->filename, dirname)) {
printf("目录重名\n");
free(buf);
return;
}
if (fileFcb->free == 0)
i--;
}
for (i = 0; i < MAXOPENFILE; ++i) {
if (openfilelist[i].topenfile == 0) {
break;
}
}
if (i == MAXOPENFILE) {
printf("无剩余openuserlist项!\n");
free(buf);
return;
}
int freeBlock = dirst_block();
if (freeBlock==-1) {
printf("FAT已满!\n");
free(buf);
return;
}
//为新目录分配fcb
fileFcb = (fcb *)buf;
int isroot = is_rootdir(fileFcb);
for (i = 0; i < fcb_num; i++, fileFcb++) {
if (!strcmp(fileFcb->filename, ".")) {
fileFcb->length += sizeof(fcb);
}
//when root is current directory
if(isroot&& !strcmp(fileFcb->filename, ".."))fileFcb->length += sizeof(fcb);
if (fileFcb->free == 0)break;
}
//update openfilelist
openfilelist[curOpenNum].length += sizeof(fcb);
fast_dirfcb(fileFcb, dirname, freeBlock);
fast_dir(freeBlock, 0);
do_write(curOpenNum, buf, 1024, 0);
free(buf);
}
void my_rm(char *filename) {
// 读取当前目录文件的内容到内存
char *buf = (char *)malloc(1024);;
int i=get_curnum();
int fd = i;
do_read(i, 1024, buf);
// 检查要删除的目录是否存在
fcb *fileFcb = (fcb *)buf;
fileFcb = exist_file(fileFcb, filename);
if (!fileFcb) {
printf("%s文件(目录)不存在!\n", filename);
return;
}
if(fileFcb->attribute==0){
printf("不能删除目录\n");
free(buf);
return;
} else {
int j;
for(j=0;jfilename)) {
printf("文件正在被使用");
free(buf);
return;
}
}
}
// 回收磁盘块
int index = fileFcb->first;
int indexT;
do {
indexT = fat1[index].id;
fat1[index].id = FREE;
fat2[index].id = FREE;
index = indexT;
} while (index != END);
// 清空目录项
fileFcb->filename[0] = '\0';
fileFcb->free = 0;
fileFcb = (fcb *)buf;
// 修改目录的长度
fileFcb->length -= sizeof(fcb);
do_write(fd, buf, 1024, 0);
ptrcurdir->length -= sizeof(fcb);
free(buf);
}
void my_close(int fd) {
if (fd >= MAXOPENFILE)
{
printf("fd不是有效数字\n");
return;
}
else if (openfilelist[fd].topenfile == 0) {
printf("文件未打开!\n");
return;
}
//else if (openfilelist[fd].fcbstate == 1) {
// //暂时只需要改length
// update_fcb(fd);
//}
clean_openfilelist(fd);
}
void my_rmdir(char *dirname) {
int i = 0;
char *buf = (char *)malloc(1024);
i = get_curnum();
int fd = i;
do_read(i, 1024, buf);
// 检查要删除的目录是否存在
fcb *fileFcb = (fcb *)buf;
fileFcb = exist_file(fileFcb, dirname);
if (!fileFcb) {
printf("%s文件(目录)不存在!\n", dirname);
return;
}
// 检查要删除的目录文件是否为空
fcb *temp = (fcb *)(myvhard + BLOCKSIZE * fileFcb->first);
if (temp->length > 2 * sizeof(fcb)) {
printf("目录不为空,不可删除!\n");
return;
}
int flag = 0;
// 检查该目录是否已经打开
for (i = 0; i < MAXOPENFILE; i++) {
if (strcmp(openfilelist[i].filename, dirname) == 0) {
flag = 1;
break;
}
}
if (flag == 1) {//f 把打开的目录关闭
my_close(i);
}
// 回收磁盘块
int index = fileFcb->first;
int indexT;
//length = fileFcb->length;
do {
indexT = fat1[index].id;
fat1[index].id = FREE;
fat2[index].id = FREE;
index = indexT;
} while (index != END);
// 清空目录项,将其free设置为0即可,然后是将上层目录的长度进行更新,同时对于openlist中也要更新,因为其指向并不相同.
fileFcb->filename[0] = '\0';
fileFcb->free = 0;
fileFcb = (fcb *)buf;
fileFcb->length -=sizeof(fcb);
ptrcurdir->length -= sizeof(fcb);
do_write(fd, buf, 1024, 0);
free(buf);
}
void my_create(char *filename) {
int i = get_curnum();
int curOpenNum = i;
int block_num = get_block_num(openfilelist[i].first);
int fcb_num = openfilelist[i].length / sizeof(fcb);
char *buf = (char *)malloc(block_num * 1024);
/* 把所有块的数据都读到buf里面去*/
do_read(i, block_num * 1024, buf);
fcb *fileFcb = (fcb *)buf;
for (i = 0; i < fcb_num; i++, ++fileFcb) {
if (!strcmp(fileFcb->filename, filename)) {
printf("文件重名!");
free(buf);
return;
break;
}
if (fileFcb->free == 0)
i--;
}
int freeBlock = dirst_block();
if (freeBlock == -1) {
free(buf);
return;
}
// 在当前目录中分配FCB给新的目录fcb
fileFcb = (fcb *)buf;
for (i = 0; i < fcb_num; ++i, ++fileFcb) {
if (!strcmp(fileFcb->filename, ".")) {
fileFcb->length += sizeof(fcb);
/* check if it is root directory*/
if (fileFcb->first == 5)(fileFcb + 1)->length = fileFcb->length;
}
if (fileFcb->free == 0)
break;
}
fast_file(fileFcb, filename, freeBlock);
ptrcurdir->length += sizeof(fcb);
do_write(curOpenNum, buf, 1024, 0);
free(buf);
}
void my_cd(char *dirname) {
// 打开该目录文件
int fd = my_open(dirname);
switch (fd) {
case -1:break;
case -2:break;
case -3:update_dir_father(); break;
default:update_dir(dirname); break;
}
}
int my_open(char *filename) {
int i = get_curnum();
fcb *p = (fcb*)(myvhard + (openfilelist[i].first)*BLOCKSIZE);
int block_num = get_block_num(openfilelist[i].first);
int fcb_num = openfilelist[i].length / sizeof(fcb);
char *buf = (char *)malloc(block_num * 1024);
/* 把所有块的数据都读到buf里面去*/
do_read(i, block_num * 1024, buf);
fcb *fileFcb = (fcb *)buf;
int flag = 0;
//找到此fcb,同时检查文件存不存在
for (i = 0; i < fcb_num; i++, fileFcb++) {
if (!strcmp(fileFcb->filename, filename)) {
flag = 1;
break;
}
}
if (flag == 0) {
printf("文件不存在!\n");
return -2;
}
//得到真正的pcb指针
p+=(fileFcb - (fcb*)buf);
// 检查文件是否已打开
for (i = 0; i < MAXOPENFILE; i++) {
if (openfilelist[i].topenfile == 1 && openfilelist[i].first == fileFcb->first) { //用first来判断是否同一个文件,注意不能用filename
if (!strcmp(fileFcb->filename, "..") && (ptrcurdir->first != 5)) { //如果是打开上个目录并且不是在根目录
// 找到当前文件夹并关闭
int j = 0;
for (j = 0; jfirst)
ptrcurdir = &openfilelist[j];
free(buf);
printf("打开上级目录!\n");
return -3;
}
free(buf);
printf("文件已打开!\n");
return -1;
}
}
// 检查opefilelist是否有空余
int fd;
flag = 0;
for (i = 0; i < MAXOPENFILE; i++) {
if (openfilelist[i].topenfile == 0) {
fd = i;
flag = 1;
break;
}
}
if (flag == 0) {
printf("文件打开太多!\n");
free(buf);
return -1;
}
// 填写打开分配的openfilelist
fcbcpy(i, p);
if(fileFcb->attribute==0)ptrcurdir = &openfilelist[i];
if(fileFcb->attribute==1)printf("打开文件的fd是%d\n", fd);
free(buf);
return fd;
}
void my_write(int fd) {
if (openfilelist[fd].attribute == 0) {
printf("can't write directory!\n");
return;
}
int writeStyle;
char *text = (char *)malloc(BLOCKSIZE);
int index = -1;
char c_temp;
unsigned short block_index=openfilelist[fd].first;
if (fd >= MAXOPENFILE || fd < 0) {
printf("fd超出范围\n");
return;
}
printf("请选择写入方式(0.覆盖写 1.追加写 2.覆盖写一行 3.追加写一行)\n");
scanf("%d", &writeStyle);
getchar();
printf("请输入内容:\n");
while ((c_temp = getchar()) != '\n')text[(++index)] = c_temp;
if (writeStyle == 2 || writeStyle == 3) {
text[(++index)] = '\n';
writeStyle -= 2;
}
int len = (index + 1);
int writed_len = do_write(fd, text, len, writeStyle); //返回实际写入字节数;
if (writed_len != -1 && writed_len == len) {
printf("写入成功,共写入 %d 个字节\n", writed_len);
//update openfilelist
if (writeStyle == 0) {
openfilelist[fd].count=openfilelist[fd].length = len;
openfilelist[fd].ptrfcb->length = len;
}
else {
openfilelist[fd].count += len;
openfilelist[fd].length = openfilelist[fd].count;
openfilelist[fd].ptrfcb->length = openfilelist[fd].count;
}
openfilelist[fd].fcbstate = 1;
}
else printf("something wrong in writing!\n");
free(text);
}
void my_read(int fd, int len) {
int i;
int j = 0;
for (i = 0; i < MAXOPENFILE; i++) {
if (fd == 0)break;
if (openfilelist[i].topenfile == 1)fd--;
}
fd = i;
char *text = (char *)malloc(BLOCKSIZE);
if (fd>MAXOPENFILE || fd<0)printf("超过操作边界\n");
else {
printf("读出字节数:%d\n",do_read(fd,len,text));
text[len]='\0';
printf("%s\n", text);
}
free(text);
}
int do_read(int fd, int len, char *text) {
int block_index = openfilelist[fd].first;
/*读写指针*/
unsigned char *p = block_index * BLOCKSIZE + myvhard;
int block_num =len%BLOCKSIZE==0?(len/BLOCKSIZE):(len / BLOCKSIZE + 1);
int i, j, k = 0;
//可能占据了多个盘块
for (i = 0; i < block_num; i++) {
for (j = 0; j < BLOCKSIZE && k < len; j++, k++, p++)text[k] = *p;
p = myvhard + BLOCKSIZE * (fat1[block_index].id);
block_index = fat1[block_index].id;
}
return k;
}
int do_write(int fd, char *text, int len, int wstyle) {
if (wstyle != 0&& wstyle != 1)return -1;
int index = openfilelist[fd].first;
unsigned char *p = index * BLOCKSIZE + myvhard;
int block_num = getblocknum_fromfilelen(len);
int i, j, k = 0;
if (wstyle == 0) {
for (i = 0; i < block_num; ++i) {
for (j = 0; j < BLOCKSIZE && k < len; ++j, ++k,++p)*p = text[k];
p = myvhard + BLOCKSIZE * (fat1[index].id);
index = fat1[index].id;
}
}
else {
int i;
int file_len = openfilelist[fd].length;
for (i = 0; i < file_len; ++i)++p;
int new_file_len = file_len + len;
int old_block = getblocknum_fromfilelen(file_len);
int new_block = getblocknum_fromfilelen(new_file_len);
check_enough_block(openfilelist[fd].first,new_block);
for (i = old_block; i <= new_block; ++i) {
for (j = (file_len-1)%BLOCKSIZE; j < BLOCKSIZE && k < len; ++j, ++k,++p)*p = text[k];
p = myvhard + BLOCKSIZE * (fat1[index].id);
index = fat1[index].id;
}
}
return k;
}
void showOpenFile() {
int i;
for (i = 0; i < MAXOPENFILE; i++) {
if (openfilelist[i].topenfile == 1)
printf("%d %s\n", i, openfilelist[i].filename);
}
}
void my_exitsys() {
//for (int i = 0; i < MAXOPENFILE; ++i) {
// if (openfilelist[i].topenfile == 1 && openfilelist[i].attribute == 1 && openfilelist[i].fcbstate == 1)
// update_fcb(i);
//}
FILE *fp;
fp = fopen("./my_fs", "w");
fwrite(myvhard, SIZE, 1, fp);
free(myvhard);
fclose(fp);
exit(0);
}
void switcher(char *cmd) {
int fd;
char command[20];
if (!strcmp(cmd, "help")) {
help();
}
else if (!strcmp(cmd, "info")) {
info();
}
else if (!strcmp(cmd, "mkdir")) {
scanf("%s", command);
if (strlen(command)>=8) printf("目录名过长\n");
else my_mkdir(command);
}
else if (!strcmp(cmd, "rmdir")) {
scanf("%s", command);
my_rmdir(command);
}
else if (!strcmp(cmd, "ls")) {
my_ls();
}
else if (!strcmp(cmd, "cd")) {
scanf("%s", command);
my_cd(command);
}
else if (!strcmp(cmd, "create")) {
scanf("%s", command);
if (strlen(command)>=8) printf("文件名过长\n");
else my_create(command);
}
else if (!strcmp(cmd, "write")) {
scanf("%d", &fd);
my_write(fd);
}
else if (!strcmp(cmd,"rm")) {
scanf("%s",command);
my_rm(command);
}
else if (!strcmp(cmd, "read")) {
scanf("%d", &fd);
my_read(fd, openfilelist[fd].length);
}
else if (!strcmp(cmd, "ls")) {
scanf("%s", command);
my_rm(command);
}
else if (!strcmp(cmd, "open")) {
scanf("%s", command);
my_open(command);
}
else if (!strcmp(cmd, "close")) {
scanf("%d", &fd);
my_close(fd);
}
else if (!strcmp(cmd, "exit")) {
my_exitsys();
return;
}
else if (!strcmp(cmd, "show")) {
showOpenFile();
}
else {
char c;
while (1) {
c = getchar();
if (c == '\n') break;
}
printf("无效指令,请重新输入:\n");
}
}
int main(int argc, const char * argv[]) {
printf("*\t输入help以获取帮助!\n");
startsys();
char cmd[10];
while (1) {
printf("%s:$", currentdir);
scanf("%s", cmd);
switcher(cmd);
}
return 0;
}