//等待子进程调用exit,将子进程的退出状态保存到status指向的变量 //成功则返回子进程的pid,失败返回-1 pid_t sys_wait(int32_t* status){ struct task_struct* parent_thread = running_thread(); while(1){ //优先处理已经是挂起状态的任务 struct list_elem* child_elem = list_traversal(&thread_all_list,find_hanging_child,parent_thread->pid); //若有挂起的任务 if(child_elem != NULL){ struct task_struct* child_thread = elem2entry(struct task_struct,all_list_tag,child_elem); *status = child_thread->exit_status; //thread_exit之后,pcb会被回收,因此提前获取pid uint16_t child_pid = child_thread->pid; //从就绪队列和全部队列中删除进程表项 thread_exit(child_thread,false); //传入false,使thread_exit调用后回到此处 //进程表项是进程或线程的最后保留的资源,至此该进程彻底消失了 return child_pid; } //判断是否有子进程 child_elem = list_traversal(&thread_all_list,find_child,parent_thread->pid); if(child_elem == NULL){ //若没有子进程则出错返回 return -1; }else{ //若子进程还未运行完,即还未调用exit,则将自己挂起,直到子进程在执行exit时将自己唤醒 thread_block(TASK_WAITING); } } }
//硬盘数据结构初始化 void ide_init(){ printk("ide_init start\n"); uint8_t hd_cnt = *((uint8_t*)(0x475)); //获取硬盘的数量 ASSERT(hd_cnt > 0); list_init(&partition_list); channel_cnt = DIV_ROUND_UP(hd_cnt,2); //一个ide通道上有两个硬盘,根据硬盘数量反推有几个ide通道 struct ide_channel* channel; uint8_t channel_no = 0,dev_no = 0; //处理每个通道上的硬盘 while(channel_no < channel_cnt){ channel = &channels[channel_no]; sprintf(channel->name,"ide%d",channel_no); //为每个ide通道初始化端口基址及中断向量 switch(channel_no){ case 0: channel->port_base = 0x1f0; //ide0通道的起始端口号为0x1f0 channel->irq_no = 0x20 + 14; //从片8259a上倒数第二的中断引脚,也就是ide0通道的中断向量号 break; case 1: channel->port_base = 0x170; //ide1通道的起始端口号为0x170 channel->irq_no = 0x20 + 15; //从片8259a上最后一个引脚,我们用来响应ide1通道上的硬盘中断 break; } channel->expecting_intr = false; //为向硬盘写入指令时不期待硬盘的中断 lock_init(&channel->lock); //初始化为0,目的是向硬盘控制器请求数据后,硬盘驱动sema_down此信号量会阻塞线程 //直到硬盘完成后通过发中断,以后中断处理程序将此信号量sema_up,唤醒线程 sema_init(&channel->disk_done,0); register_handler(channel->irq_no,intr_hd_handler); /* 分别获取两个硬盘的参数及分区信息 */ while (dev_no < 2) { struct disk* hd = &channel->devices[dev_no]; hd->my_channel = channel; hd->dev_no = dev_no; sprintf(hd->name, "sd%c", 'a' + channel_no * 2 + dev_no); identify_disk(hd); // 获取硬盘参数 if (dev_no != 0) { // 内核本身的裸硬盘(hd60M.img)不处理 partition_scan(hd, 0); // 扫描该硬盘上的分区 } p_no = 0, l_no = 0; dev_no++; } dev_no = 0; channel_no++; //下一个channel } printk("\n all partition info\n"); /* 打印所有分区信息 */ list_traversal(&partition_list, partition_info, (int)NULL); printk("ide_init done\n"); }
int main() { List *L = list_create(&cmp); int num = 10; int i = 0; int *key = NULL; for (i = 0; i < num; i++) { key = malloc(sizeof(int)); *key = i; list_insert(L, key); } list_traversal(L, visit); list_retraversal(L, visit); printf("\n"); key = malloc(sizeof(int)); *key = 2; key = list_delete(L, key); list_traversal(L, visit); printf("\n"); return 0; }
//子进程用来结束自己时调用 void sys_exit(int32_t status){ struct task_struct* child_thread = running_thread(); child_thread->exit_status = status; if(child_thread->parent_pid == -1){ PANIC("sys_exit: child_thread->parent_pid is -1\n"); } //将进程child_thread的所有子进程都过继给init list_traversal(&thread_all_list,init_adopt_a_child,child_thread->pid); //回收进程child_thread的资源 release_prog_resource(child_thread); //如果父进程正在等待子进程退出,将父进程唤醒 struct task_struct* parent_thread = pid2thread(child_thread->parent_pid); if(parent_thread->status == TASK_WAITING){ thread_unblock(parent_thread); } //将自己挂起,等待父进程获取其status,并回收其pcb thread_block(TASK_HANGING); }
/* 在磁盘上搜索文件系统,若没有则格式化分区创建文件系统 */ void filesys_init() { uint8_t channel_no = 0, dev_no, part_idx = 0; /* sb_buf用来存储从硬盘上读入的超级块 */ struct super_block* sb_buf = (struct super_block*)sys_malloc(SECTOR_SIZE); if (sb_buf == NULL) { PANIC("alloc memory failed!"); } printk("searching filesystem......\n"); while (channel_no < channel_cnt) { dev_no = 0; while(dev_no < 2) { if (dev_no == 0) { // 跨过裸盘hd60M.img dev_no++; continue; } struct disk* hd = &channels[channel_no].devices[dev_no]; struct partition* part = hd->prim_parts; while(part_idx < 12) { // 4个主分区+8个逻辑 if (part_idx == 4) { // 开始处理逻辑分区 part = hd->logic_parts; } /* channels数组是全局变量,默认值为0,disk属于其嵌套结构, * partition又为disk的嵌套结构,因此partition中的成员默认也为0. * 若partition未初始化,则partition中的成员仍为0. * 下面处理存在的分区. */ if (part->sec_cnt != 0) { // 如果分区存在 memset(sb_buf, 0, SECTOR_SIZE); /* 读出分区的超级块,根据魔数是否正确来判断是否存在文件系统 */ ide_read(hd, part->start_lba + 1, sb_buf, 1); /* 只支持自己的文件系统.若磁盘上已经有文件系统就不再格式化了 */ if (sb_buf->magic == 0x19590318) { printk("%s has filesystem\n", part->name); } else { // 其它文件系统不支持,一律按无文件系统处理 printk("formatting %s`s partition %s......\n", hd->name, part->name); partition_format(part); } } part_idx++; part++; // 下一分区 } dev_no++; // 下一磁盘 } channel_no++; // 下一通道 } sys_free(sb_buf); /* 确定默认操作的分区 */ char default_part[8] = "sdb1"; /* 挂载分区 */ list_traversal(&partition_list, mount_partition, (int)default_part); /* 将当前分区的根目录打开 */ open_root_dir(cur_part); /* 初始化文件表 */ uint32_t fd_idx = 0; while (fd_idx < MAX_FILE_OPEN) { file_table[fd_idx++].fd_inode = NULL; } }