FreeFlyOS【十五】:task部分详解

task.c

#include "task.h"
#include "../interrupt/syscall.h"
#include "../stl/elf.h"
#include "../mem/pmm.h"
#include "../mem/vmm.h"
#include "../mem/memlayout.h"
#include "../debug/debug.h"
#include "../sync/sync.h"
#include "../file/file.h"
#include "../file/inode.h"
#define HASH_SHIFT          10
#define HASH_LIST_SIZE      (1 << HASH_SHIFT)
#define pid_hashfn(x)       (hash32(x, HASH_SHIFT))


/*
#define __KERNEL_EXECVE(name, binary, size) ({                          \
            printk("kernel_execve: pid = %d, name = \"%s\".\n",        \
                    current->pid, name);                                \
            kernel_execve(name, binary, (unsigned int)(size));                \
        })
//#x 表示字符串操作符,即"x"
//##x##表示连接符  
#define KERNEL_EXECVE(x) ({                                             \
            extern unsigned char _binary_##x##_out_start[],  \
                _binary_##x##_out_size[];                    \
            __KERNEL_EXECVE(#x, _binary_##x##_out_start,     \
                            _binary_##x##_out_size);         \
        })

#define __KERNEL_EXECVE2(x, xstart, xsize) ({                           \
            extern unsigned char xstart[], xsize[];                     \
            __KERNEL_EXECVE(#x, xstart, (unsigned int)xsize);                 \
        })

#define KERNEL_EXECVE2(x, xstart, xsize)       __KERNEL_EXECVE2(x, xstart, xsize)
*/
// 绑定PID的哈希表
static list_entry_t hash_list[HASH_LIST_SIZE];

//PID 位图初始化
pidmap_t task_pidmap={pid_max,{0}}; 
static unsigned int volatile last_pid=0;

//就绪进程链表
static list_entry_t ready_task_list;
//所有进程链表
static list_entry_t all_task_list;
struct task_struct *task0;  //祖先进程,即进程0
struct task_struct *user_task; //第一个用户进程
//struct task_struct *task1;  //由进程0 do_fork出来的进程1
struct task_struct *current;  //指向当前进程

extern struct semaphore user_sema;

//MACOS下容易出现BUG
//静态全局变量设置为0值时,在运行的时候容易跑飞,所以为了避免出现BUG,在使用的时候应先定义0值
static unsigned int volatile nr_task=0; //当前所有进程数量  

void forkrets(struct trapframe *tf);

extern unsigned int __trapret;
extern struct file file_table[MAX_FILE_OPEN];
extern struct segdesc gdt[];
extern unsigned int new_pdt[PAGE_DIR_SIZE] __attribute__( (aligned(VMM_PAGE_SIZE) ) );
extern unsigned int user_pt_highmem[(unsigned int)0xC0000000/
((unsigned int)PAGE_TABLE_SIZE*(unsigned int)VMM_PAGE_SIZE)]
[PAGE_TABLE_SIZE]__attribute__( (aligned(VMM_PAGE_SIZE) ) );
struct task_struct *task0,*task1;
/*
*   kernel_task_init:创建第一个内核进程
*/
void kernel_task_init(void *function){

    /*就绪进程链表初始化*/
    list_init(&ready_task_list);
    /*所有进程链表初始化*/
    list_init(&all_task_list);
    /*哈希链表初始化*/
    for(int i=0;i<HASH_LIST_SIZE;i++){
        list_init(&hash_list[i]);
    }
    //分配task_struct结构体
    if((task0=alloc_task(KERNEL_TASK))==NULL){
        printk("alloc task error!\n");
    }
    
    /* 设置task0属性 */
    task0->state=STOPPED;   
    task0->counter=5;
    task0->priority=1; 
    last_pid=task0->pid=0;  //初始化task0的PID和last_pid
    set_task_name(task0,"kernel_task");
    task0->kernel_stack=(unsigned int)task0+VMM_PAGE_SIZE;
    task0->cr3=LA_PA((unsigned int)new_pdt);
    task0->cwd_inode_nr=0;

        
    task0->tf = (struct trapframe *)(task0->kernel_stack)- 1;
    task0->tf->tf_regs.reg_eax=0;
    task0->tf->tf_regs.reg_ebp=0;
    task0->tf->tf_regs.reg_ebx=0;
    task0->tf->tf_regs.reg_ecx=0;
    task0->tf->tf_regs.reg_edi=0;
    task0->tf->tf_regs.reg_edx=0;
    task0->tf->tf_regs.reg_esi=0;
    task0->tf->tf_regs.reg_oesp=0;

    task0->tf->tf_cs=KERNEL_CS;
    task0->tf->tf_ds=task0->tf->tf_es=task0->tf->tf_fs=task0->tf->tf_ss=KERNEL_DS;
    task0->tf->tf_gs=0;
    task0->tf->tf_eip=0;//function; //user_space1
    task0->tf->tf_eflags=(EFLGAS_IOPL_0|EFLAGS_MBS|EFLAGS_IF_1);

    task0->tf->tf_esp=task0->kernel_stack-sizeof(struct trapframe);
    
    /*设置用户的上下文*/
    task0->context.eip=function;//task0->tf->tf_eip;
    task0->context.esp= (unsigned int)(task0->tf); 
    task0->context.ebx=task0->tf->tf_regs.reg_ebx;
    task0->context.edx=task0->tf->tf_regs.reg_edx;

    /* 进程链表指向task0 */
    //ask_list=task0->link;   //待调试
    //memcpy(&(task_list),&(task0->link),sizeof(list_entry_t));
    //list_init(&task0->link);
    //插入就绪任务链表
    list_init(&task0->link);
    add_link(&task0->link);
    //插入所有任务链表
    list_init(&task0->all_link);
    add_all_link(&task0->all_link);
    task0->fd_table[0]=0;
    task0->fd_table[1]=1;
    task0->fd_table[2]=2;
    for(int i=3;i<MAX_FILE_OPEN;i++){
        task0->fd_table[i]=-1;
    }
    /* 当前进程指向task0 */
    current=task0;
    
    //clear();
    //printk("task0->counter:%08d!\n",task0->counter);
    //printk("current:%08X!\n",current);
    //printk("In task_init,current->counter=%08d\n",current->counter);
    /* 根据PID加入哈希链表 */
    add_pid_hash(task0);
    
    wakeup_task(task0);
    //这时候直接赋值,以免静态全局变量在不同编译器下跑飞
    //nr_task++;
    nr_task=1;
}
//设置PID位
static int set_pid_bit(int pid){
    //获取PID所在的字节号
    int chars=pid/8;
    //获取PID所在字节的偏移位
    int offset=pid%8;
    //置位
    set_char_bit(task_pidmap.bits[chars],offset,1);
}
//清除PID位
static int clear_pid_bit(int pid){
    //获取PID所在的字节号
    int chars=pid/8;
    //获取PID所在字节的偏移位
    int offset=pid%8;
    //清零
    set_char_bit(task_pidmap.bits[chars],offset,0);
}
//返回未被占用的PID号,若没有则返回-1
static int find_free_pid(){
    int i=0,k=0;
    while(k!=32768){
        for(int j=0;j<8;j++,k++){
            if((task_pidmap.bits[i]>>j)&1==0){
                return k;
            }
        }
        i++;
    }
    return -1;
}
//分配一个可用的PID
static int alloc_pid(){

    //若无多余的PID号
    if(!task_pidmap.nr_free){
        return -1;
    }
    /*
    ** 一般将PID号设置为上个进程PID号+1
    **  若PID号已设置到末尾,则查询位图中是否还有未被占用的PID号
    */
    int pid=(pid==32767)?find_free_pid():last_pid+1;
    
    //有效PID
    if(pid>=0){
        set_pid_bit(pid);
        task_pidmap.nr_free--;
    }
    last_pid=pid;
    return pid;
}
//释放一个PID
static void free_pid(int pid){
    clear_pid_bit(pid);
    task_pidmap.nr_free++;
}

// 设置进程名称
char *set_task_name(struct task_struct *task, const char *name) {
    memset(task->name, 0, sizeof(task->name));
    return memcpy(task->name, name, task_name_max);
}

// 获取进程名称
char *get_task_name(struct task_struct *task) {
    static char name[task_name_max + 1];
    memset(name, 0, sizeof(name));
    return memcpy(name, task->name, task_name_max);
}

//将新进程插入就绪进程链表队尾
static void add_link(list_entry_t *new){
    list_add_before(&ready_task_list,new);
}
//将新进程插入所有进程链表队尾
static void add_all_link(list_entry_t *new){
    list_add_before(&all_task_list,new);
}

//在进程链表中删除某个进程
static void remove_link(list_entry_t *node){
    list_del(node);
}

//根据PID加入到PID哈希表中
static void add_pid_hash(struct task_struct *task){
    list_add(hash_list+pid_hashfn(task->pid),&(task->hash_link));
}

//根据PID删除哈希表中的节点
static void remove_pid_hash(int pid){
    struct task_struct *task=find_task(pid);
    list_del(&(task->hash_link)); 
}

//给定PID,在哈希表查找进程
static struct task_struct* find_task(int pid){
    
    if(pid<0){
        return NULL;
    }
    //找到哈希链表头
    list_entry_t *head=&hash_list[pid_hashfn(pid)];
    list_entry_t *ite=head;
    
    //在哈希表头下的双向循环链表(不包含哈希表头)中查找PID对应的进程
    while((ite=list_next(ite))!=head){
        struct  task_struct *task=list_to_task(ite,hash_link);
        if(task->pid==pid){
            return task;
        }
    } 
    //未找到
    return NULL;
}

//给进程分配task_struct结构体,判断是用户进程还是内核进程
static struct task_struct* alloc_task(enum task_kind kind){
    struct task_struct *task;
    if(kind==KERNEL_TASK)
        task=vmm_malloc(VMM_PAGE_SIZE*2,1);
    else
        task=vmm_malloc(VMM_PAGE_SIZE*2,2);
    
    if(task!=NULL){
        task->state=UNRUNNABLE;
        task->counter=5;
        task->priority=0;
        task->pid=-1;
        memset(&(task->name),0,sizeof(task->name));
        task->kernel_stack=0;
        task->cr3=new_pdt;
        task->tf=NULL;
        memset(&(task->context),0,sizeof(task->context));
        task->magic=TASK_MAGIC;
        task->cwd_inode_nr=0;
        for(int i=0;i<MAX_FILE_OPEN;i++){
        task->fd_table[i]=-1;
    }
    }
    return task;
}

/* 由kernel_thread去执行function(func_arg) */
//static void kernel_thread(thread_func* function, void* func_arg) {
/* 执行function前要开中断,避免后面的时钟中断被屏蔽,而无法调度其它线程 */
//   intr_enable();
//  function(func_arg); 
//}

// forkret -- t
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值