Kaynağa Gözat

实现设置pcb名字和vsnprintf (#72)

* 实现pcb设置名字

* 实现设置pcb名字,实现vsnprintf

* 修改set_pcb_name和va_end

* bugfix: 修正一些小问题

Co-authored-by: longjin <longjin@RinGoTek.cn>
houmkh 2 yıl önce
ebeveyn
işleme
8e3f5674f8

+ 18 - 1
kernel/common/kthread.h

@@ -5,6 +5,22 @@
 #include <common/err.h>
 #include <process/process.h>
 
+/**
+ * @brief kthread信息
+ * 该结构体将会绑定到pcb的worker_private中
+ */
+struct kthread_info_t
+{
+    uint64_t flags;
+    uint32_t cpu;
+    int result;
+    int (*thread_fn)(void *);
+    void *data;
+    // todo: 将这里改为completion机制
+    bool exited;     // 是否已退出
+    char *full_name; // 内核线程的名称
+};
+
 struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data),
                                                      void *data,
                                                      int node,
@@ -74,4 +90,5 @@ int kthread_mechanism_init();
  * @param pcb pcb
  * @return bool 成功或失败
  */
-bool kthread_set_worker_private(struct process_control_block *pcb);
+bool kthread_set_worker_private(struct process_control_block *pcb);
+

+ 12 - 0
kernel/common/printk.h

@@ -38,6 +38,7 @@
 
 extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap(8*16大小) ps:位于font.h中
 
+
 /**
  * @brief 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
  *
@@ -48,6 +49,17 @@ extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap(8*16大
  */
 int vsprintf(char *buf, const char *fmt, va_list args);
 
+/**
+ * @brief 将字符串按照fmt和args中的内容进行格式化,截取字符串前buf_size-1,保存到buf中
+ *
+ * @param buf 结果缓冲区,大小为buf_size
+ * @param fmt 格式化字符串
+ * @param buf_size 缓冲区长度
+ * @param args 内容
+ * @return 最终字符串的长度
+ */
+int vsnprintf(char *buf, const char *fmt, int buf_size, va_list args);
+
 /**
  * @brief 格式化打印字符串
  *

+ 2 - 2
kernel/filesystem/VFS/VFS.c

@@ -796,12 +796,12 @@ int do_unlink_at(int dfd, const char *pathname, bool from_userland)
 
     struct vfs_index_node_t *p_inode = dentry->parent->dir_inode;
     // 对父inode加锁
-    spin_lock(&p_inode);
+    spin_lock(&p_inode->lockref.lock);
     retval = vfs_unlink(NULL, dentry->parent->dir_inode, dentry, NULL);
 
     spin_lock(&dentry->lockref.lock);
     retval = vfs_dentry_put(dentry);
-    spin_unlock(&p_inode);
+    spin_unlock(&p_inode->lockref.lock);
 
     if (IS_ERR(retval))
         kwarn("In do_unlink_at: dentry put failed; retval=%d", retval);

+ 56 - 6
kernel/lib/printk.c

@@ -42,18 +42,22 @@ static int skip_and_atoi(const char **s)
 }
 
 /**
- * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
+ * @brief 将字符串按照fmt和args中的内容进行格式化,当buf_size为-1时,字符串直接保存到buf中
+ * 否则将字符串前buf_size-1个字符放入,大小为buf_size的buf数组中
+ *
  * @param buf 结果缓冲区
  * @param fmt 格式化字符串
  * @param args 内容
+ * @param buf_size buf_size为-1时,不指定buf的大小,否则buf大小为buf_size
  * @return 最终字符串的长度
  */
-int vsprintf(char *buf, const char *fmt, va_list args)
+static int __do_vsprintf(char *buf, const char *fmt, int buf_size, va_list args)
 {
+
     // 当需要输出的字符串的指针为空时,使用该字符填充目标字符串的指针
     static const char __end_zero_char = '\0';
 
-    char *str = NULL, *s = NULL;
+    char *str = NULL, *s = NULL, *end = NULL;
 
     str = buf;
 
@@ -63,6 +67,10 @@ int vsprintf(char *buf, const char *fmt, va_list args)
     int qualifier;   //数据显示的类型
     int len;
 
+    if (buf_size != -1)
+    {
+        end = buf + buf_size;
+    }
     //开始解析字符串
     for (; *fmt; ++fmt)
     {
@@ -324,12 +332,54 @@ int vsprintf(char *buf, const char *fmt, va_list args)
             break;
         }
     }
-    *str = '\0';
+    //实现vsnprintf 的功能
+    if (buf_size > 0)
+    {
+        if (str < end)
+        {
+            *str = '\0';
+        }
+        else
+        {
+            *(end-1) = '\0';
+        }
+        return buf_size;
+    }
+    else
+    {
+        *str = '\0';
+    }
 
     //返回缓冲区已有字符串的长度。
     return str - buf;
 }
 
+/**
+ * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
+ * @param buf 结果缓冲区
+ * @param fmt 格式化字符串
+ * @param args 内容
+ * @return 最终字符串的长度
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+    return __do_vsprintf(buf, fmt, -1, args);
+}
+
+/**
+ * @brief 将字符串按照fmt和args中的内容进行格式化,截取字符串前buf_size-1,保存到buf中
+ *
+ * @param buf 结果缓冲区,大小为buf_size
+ * @param fmt 格式化字符串
+ * @param buf_size 缓冲区长度
+ * @param args 内容
+ * @return 最终字符串的长度
+ */
+int vsnprintf(char *buf, const char *fmt, int buf_size, va_list args)
+{
+    return __do_vsprintf(buf, fmt, buf_size, args);
+}
+
 static char *write_num(char *str, ul num, int base, int field_width, int precision, int flags)
 {
     /**
@@ -477,8 +527,8 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
     if (sign)
         --field_width;
 
-    int js_num_z = 0, js_num_d = 0;   // 临时数字字符串tmp_num_z tmp_num_d的长度
-    uint64_t num_z = (uint64_t)(num); // 获取整数部分
+    int js_num_z = 0, js_num_d = 0;                                                     // 临时数字字符串tmp_num_z tmp_num_d的长度
+    uint64_t num_z = (uint64_t)(num);                                                   // 获取整数部分
     uint64_t num_decimal = (uint64_t)(round(1.0 * (num - num_z) * pow(10, precision))); // 获取小数部分
 
     if (num == 0 || num_z == 0)

+ 25 - 25
kernel/process/kthread.c

@@ -1,8 +1,8 @@
-#include <common/kthread.h>
 #include <common/glib.h>
+#include <common/kthread.h>
 #include <common/spinlock.h>
-#include <sched/sched.h>
 #include <debug/bug.h>
+#include <sched/sched.h>
 #include <time/sleep.h>
 
 static spinlock_t __kthread_create_lock;           // kthread创建过程的锁
@@ -28,28 +28,13 @@ struct kthread_create_info_t
     void *data;
     int node;
 
-    // kthreadd守护进程传递给kthread_create的结果, 成功则返回PCB,不成功则该值为负数错误码。若该值为NULL,意味着创建过程尚未完成
+    // kthreadd守护进程传递给kthread_create的结果,
+    // 成功则返回PCB,不成功则该值为负数错误码。若该值为NULL,意味着创建过程尚未完成
     struct process_control_block *result;
 
     struct List list;
 };
 
-/**
- * @brief kthread信息
- * 该结构体将会绑定到pcb的worker_private中
- */
-struct kthread_info_t
-{
-    uint64_t flags;
-    uint32_t cpu;
-    int result;
-    int (*thread_fn)(void *);
-    void *data;
-    // todo: 将这里改为completion机制
-    bool exited;     // 是否已退出
-    char *full_name; // 内核线程的名称
-};
-
 /**
  * @brief 获取pcb中的kthread结构体
  *
@@ -62,8 +47,7 @@ static inline struct kthread_info_t *to_kthread(struct process_control_block *pc
     return pcb->worker_private;
 }
 
-static struct process_control_block *__kthread_create_on_node(int (*thread_fn)(void *data), void *data,
-                                                              int node,
+static struct process_control_block *__kthread_create_on_node(int (*thread_fn)(void *data), void *data, int node,
                                                               const char name_fmt[], va_list args)
 {
     struct process_control_block *pcb = NULL;
@@ -96,6 +80,22 @@ static struct process_control_block *__kthread_create_on_node(int (*thread_fn)(v
     if (!IS_ERR(create->result))
     {
         // todo: 为内核线程设置名字
+        char pcb_name[PCB_NAME_LEN];
+        va_list get_args;
+        va_copy(get_args, args);
+        //获取到字符串的前16字节
+        int len = vsnprintf(pcb_name, name_fmt, PCB_NAME_LEN, get_args);
+        if (len >= PCB_NAME_LEN)
+        {
+            //名字过大 放到full_name字段中
+            struct kthread_info_t *kthread = to_kthread(pcb);
+            char *full_name = kzalloc(1024, __GFP_ZERO);
+            vsprintf(full_name, name_fmt, get_args);
+            kthread->full_name = full_name;
+        }
+        //将前16Bytes放到pcb的name字段
+        process_set_pcb_name(pcb, pcb_name);
+        va_end(get_args);
     }
 
     kfree(create);
@@ -131,8 +131,7 @@ void kthread_exit(long result)
  * 当内核线程被唤醒时,会运行thread_fn函数,并将data作为参数传入。
  * 内核线程可以直接返回,也可以在kthread_should_stop为真时返回。
  */
-struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), void *data,
-                                                     int node,
+struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), void *data, int node,
                                                      const char name_fmt[], ...)
 {
     struct process_control_block *pcb;
@@ -171,7 +170,7 @@ static int kthread(void *_create)
     // 将当前pcb返回给创建者
     create->result = current_pcb;
 
-    current_pcb->state &= ~PROC_RUNNING;    // 设置当前进程不是RUNNING态
+    current_pcb->state &= ~PROC_RUNNING; // 设置当前进程不是RUNNING态
     // 发起调度,使得当前内核线程休眠。直到创建者通过process_wakeup将当前内核线程唤醒
     sched();
 
@@ -221,7 +220,8 @@ int kthreadd(void *unused)
         {
 
             // 从链表中取出第一个要创建的内核线程任务
-            struct kthread_create_info_t *create = container_of(kthread_create_list.next, struct kthread_create_info_t, list);
+            struct kthread_create_info_t *create =
+                container_of(kthread_create_list.next, struct kthread_create_info_t, list);
             list_del_init(&create->list);
             spin_unlock(&__kthread_create_lock);
 

+ 12 - 3
kernel/process/proc-types.h

@@ -34,6 +34,8 @@
 #define CLONE_SIGNAL (1UL << 1)
 #define CLONE_VM (1UL << 2) // 在进程间共享虚拟内存空间
 
+#define PCB_NAME_LEN 16
+
 struct thread_struct
 {
     // 内核层栈基指针
@@ -57,8 +59,8 @@ struct thread_struct
 #define PF_KTHREAD (1UL << 0)    // 内核线程
 #define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
 #define PF_VFORK (1UL << 2)      // 标志进程是否由于vfork而存在资源共享
-#define PF_KFORK (1UL << 3)    // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
-#define PF_NOFREEZE (1UL << 4) // 当前进程不能被冻结
+#define PF_KFORK (1UL << 3)      // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
+#define PF_NOFREEZE (1UL << 4)   // 当前进程不能被冻结
 
 /**
  * @brief 进程控制块
@@ -73,6 +75,8 @@ struct process_control_block
     int64_t preempt_count; // 持有的自旋锁的数量
     long signal;
     long cpu_id; // 当前进程在哪个CPU核心上运行
+    char name[PCB_NAME_LEN];
+
     // 内存空间分布结构体, 记录内存页表和程序段信息
     struct mm_struct *mm;
 
@@ -82,6 +86,10 @@ struct process_control_block
     // 连接各个pcb的双向链表
     struct List list;
 
+    //todo:给pcb中加一个spinlock_t成员
+    //进程自旋锁
+    // spinlock_t alloc_lock;
+
     // 地址空间范围
     // 用户空间: 0x0000 0000 0000 0000 ~ 0x0000 7fff ffff ffff
     // 内核空间: 0xffff 8000 0000 0000 ~ 0xffff ffff ffff ffff
@@ -109,7 +117,8 @@ struct process_control_block
 };
 
 // 将进程的pcb和内核栈融合到一起,8字节对齐
-union proc_union {
+union proc_union
+{
     struct process_control_block pcb;
     ul stack[STACK_SIZE / sizeof(ul)];
 } __attribute__((aligned(8)));

+ 30 - 3
kernel/process/process.c

@@ -135,8 +135,10 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
     //           initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5,
     //           initial_tss[0].ist6, initial_tss[0].ist7);
 
-    __asm__ __volatile__("movq	%%fs,	%0 \n\t" : "=a"(prev->thread->fs));
-    __asm__ __volatile__("movq	%%gs,	%0 \n\t" : "=a"(prev->thread->gs));
+    __asm__ __volatile__("movq	%%fs,	%0 \n\t"
+                         : "=a"(prev->thread->fs));
+    __asm__ __volatile__("movq	%%gs,	%0 \n\t"
+                         : "=a"(prev->thread->gs));
 
     __asm__ __volatile__("movq	%0,	%%fs \n\t" ::"a"(next->thread->fs));
     __asm__ __volatile__("movq	%0,	%%gs \n\t" ::"a"(next->thread->gs));
@@ -1194,4 +1196,29 @@ int process_fd_alloc(struct vfs_file_t *file)
         }
     }
     return fd_num;
-}
+}
+
+/**
+ * @brief 给pcb设置名字
+ *
+ * @param pcb 需要设置名字的pcb
+ * @param pcb_name 保存名字的char数组
+ */
+static void __set_pcb_name(struct process_control_block *pcb, const char *pcb_name)
+{
+    //todo:给pcb加锁
+    // spin_lock(&pcb->alloc_lock);
+    strncpy(pcb->name,pcb_name,PCB_NAME_LEN);
+    // spin_unlock(&pcb->alloc_lock);
+}
+
+/**
+ * @brief 给pcb设置名字
+ *
+ * @param pcb 需要设置名字的pcb
+ * @param pcb_name 保存名字的char数组
+ */
+void process_set_pcb_name(struct process_control_block *pcb, const char *pcb_name)
+{
+    __set_pcb_name(pcb, pcb_name);
+}

+ 8 - 0
kernel/process/process.h

@@ -222,3 +222,11 @@ extern struct mm_struct initial_mm;
 extern struct thread_struct initial_thread;
 extern union proc_union initial_proc_union;
 extern struct process_control_block *initial_proc[MAX_CPU_NUM];
+
+/**
+ * @brief 给pcb设置名字
+ *
+ * @param pcb 需要设置名字的pcb
+ * @param pcb_name 保存名字的char数组
+ */
+void process_set_pcb_name(struct process_control_block *pcb, const char *pcb_name);

+ 9 - 6
kernel/sched/sched.c

@@ -3,15 +3,15 @@
 #include <common/spinlock.h>
 #include <driver/video/video.h>
 #include <sched/cfs.h>
-
+#include <common/string.h>
 /**
- * @brief 
- * 
+ * @brief
+ *
  * @param p pcb
  * @param attr 调度属性
  * @param user 请求是否来自用户态
- * @param pi 
- * @return int 
+ * @param pi
+ * @return int
  */
 static int __sched_setscheduler(struct process_control_block *p, const struct sched_attr *attr, bool user, bool pi)
 {
@@ -70,4 +70,7 @@ void sched()
 void sched_init()
 {
     sched_cfs_init();
-}
+}
+
+
+

+ 2 - 1
kernel/sched/sched.h

@@ -75,4 +75,5 @@ void sched_init();
  * @brief 当时钟中断到达时,更新时间片
  *
  */
-void sched_update_jiffies();
+void sched_update_jiffies();
+