ling830 发表于 2026-5-11 19:35:07

一份古老的C代码

chdir/usr/sys/ken

# cat main.c
#
#include "../param.h"
#include "../user.h"
#include "../systm.h"
#include "../proc.h"
#include "../text.h"
#include "../inode.h"
#include "../seg.h"

#define CLOCK10177546
#define CLOCK20172540
/*
* Icode is the octal bootstrap
* program executed in user mode
* to bring up the system.
*/
int   icode[]
{
      0104413,      /* sys exec; init; initp */
      0000014,
      0000010,
      0000777,      /* br . */
      0000014,      /* initp: init; 0 */
      0000000,
      0062457,      /* init: </etc/init\0> */
      0061564,
      0064457,
      0064556,
      0000164,
};

/*
* Initialization code.
* Called from m40.s or m45.s as
* soon as a stack and segmentation
* have been established.
* Functions:
*      clear and free user core
*      find which clock is configured
*      hand craft 0th process
*      call all initialization routines
*      fork - process 0 to schedule
*         - process 1 execute bootstrap
*
* panic: no clock -- neither clock responds
* loop at loc 6 in user mode -- /etc/init
*      cannot be executed.
*/
main()
{
      extern schar;
      register i, *p;

      /*
         * zero and free all of core
         */

      updlock = 0;
      i = *ka6 + USIZE;
      UISD->r = 077406;
      for(;;) {
                UISA->r = i;
                if(fuibyte(0) < 0)
                        break;
                clearseg(i);
                maxmem++;
                mfree(coremap, 1, i);
                i++;
      }
      if(cputype == 70)
      for(i=0; i<62; i=+2) {
                UBMAP->r = i<<12;
                UBMAP->r = 0;
      }
      printf("mem = %l\n", maxmem*5/16);
      printf("RESTRICTED RIGHTS\n\n");
      printf("Use, duplication or disclosure is subject to\n");
      printf("restrictions stated in Contract with Western\n");
      printf("Electric Company, Inc.\n");

      maxmem = min(maxmem, MAXMEM);
      mfree(swapmap, nswap, swplo);

      /*
         * determine clock
         */

      UISA->r = ka6; /* io segment */
      UISD->r = 077406;
      lks = CLOCK1;
      if(fuiword(lks) == -1) {
                lks = CLOCK2;
                if(fuiword(lks) == -1)
                        panic("no clock");
      }

      /*
         * set up system process
         */

      proc.p_addr = *ka6;
      proc.p_size = USIZE;
      proc.p_stat = SRUN;
      proc.p_flag =| SLOAD|SSYS;
      u.u_procp = &proc;

      /*
         * set up 'known' i-nodes
         */

      *lks = 0115;
      cinit();
      binit();
      iinit();
      rootdir = iget(rootdev, ROOTINO);
      rootdir->i_flag =& ~ILOCK;
      u.u_cdir = iget(rootdev, ROOTINO);
      u.u_cdir->i_flag =& ~ILOCK;

      /*
         * make init process
         * enter scheduling loop
         * with system process
         */

      if(newproc()) {
                expand(USIZE+1);
                estabur(0, 1, 0, 0);
                copyout(icode, 0, sizeof icode);
                /*
               * Return goes to loc. 0 of user init
               * code just copied out.
               */
                return;
      }
      sched();
}

/*
* Load the user hardware segmentation
* registers from the software prototype.
* The software registers must have
* been setup prior by estabur.
*/
sureg()
{
      register *up, *rp, a;

      a = u.u_procp->p_addr;
      up = &u.u_uisa;
      rp = &UISA->r;
      if(cputype == 40) {
                up =- 8;
                rp =- 8;
      }
      while(rp > &UISA->r)
                *--rp = *--up + a;
      if((up=u.u_procp->p_textp) != NULL)
                a =- up->x_caddr;
      up = &u.u_uisd;
      rp = &UISD->r;
      if(cputype == 40) {
                up =- 8;
                rp =- 8;
      }
      while(rp > &UISD->r) {
                *--rp = *--up;
                if((*rp & WO) == 0)
                        rp[(UISA-UISD)/2] =- a;
      }
}

/*
* Set up software prototype segmentation
* registers to implement the 3 pseudo
* text,data,stack segment sizes passed
* as arguments.
* The argument sep specifies if the
* text and data+stack segments are to
* be separated.
*/
estabur(nt, nd, ns, sep)
{
      register a, *ap, *dp;

      if(sep) {
                if(cputype == 40)
                        goto err;
                if(nseg(nt) > 8 || nseg(nd)+nseg(ns) > 8)
                        goto err;
      } else
                if(nseg(nt)+nseg(nd)+nseg(ns) > 8)
                        goto err;
      if(nt+nd+ns+USIZE > maxmem)
                goto err;
      a = 0;
      ap = &u.u_uisa;
      dp = &u.u_uisd;
      while(nt >= 128) {
                *dp++ = (127<<8) | RO;
                *ap++ = a;
                a =+ 128;
                nt =- 128;
      }
      if(nt) {
                *dp++ = ((nt-1)<<8) | RO;
                *ap++ = a;
      }
      if(sep)
      while(ap < &u.u_uisa) {
                *ap++ = 0;
                *dp++ = 0;
      }
      a = USIZE;
      while(nd >= 128) {
                *dp++ = (127<<8) | RW;
                *ap++ = a;
                a =+ 128;
                nd =- 128;
      }
      if(nd) {
                *dp++ = ((nd-1)<<8) | RW;
                *ap++ = a;
                a =+ nd;
      }
      while(ap < &u.u_uisa) {
                *dp++ = 0;
                *ap++ = 0;
      }
      if(sep)
      while(ap < &u.u_uisa) {
                *dp++ = 0;
                *ap++ = 0;
      }
      a =+ ns;
      while(ns >= 128) {
                a =- 128;
                ns =- 128;
                *--dp = (127<<8) | RW;
                *--ap = a;
      }
      if(ns) {
                *--dp = ((128-ns)<<8) | RW | ED;
                *--ap = a-128;
      }
      if(!sep) {
                ap = &u.u_uisa;
                dp = &u.u_uisa;
                while(ap < &u.u_uisa)
                        *dp++ = *ap++;
                ap = &u.u_uisd;
                dp = &u.u_uisd;
                while(ap < &u.u_uisd)
                        *dp++ = *ap++;
      }
      sureg();
      return(0);

err:
      u.u_error = ENOMEM;
      return(-1);
}

/*
* Return the arg/128 rounded up.
*/
nseg(n)
{

      return((n+127)>>7);
}
#

FishC 发表于 2026-5-11 19:35:30

这是一份非常经典的 Unix V6 内核(大约 1975 年)的 main.c 文件,来自贝尔实验室。它负责计算机启动后 第一个用户态进程的创建 和系统初始化。下面用通俗的方式解释核心逻辑:


[*]清除用户核心:循环扫描所有未被内核占用的内存页,用 clearseg 清零,并调用 mfree 归还给空闲内存管理表(coremap)。
[*]检测时钟:检查两个可能的时钟地址(CLOCK1 和 CLOCK2),如果都失败则调用 panic("no clock")。
[*]建立 0 号进程(系统进程):手动设置 proc 结构,赋予 SRUN(就绪)状态和 SSYS(系统进程)标志。
[*]初始化文件系统:调用 cinit()(字符设备)、binit()(块设备)、iinit()(i 节点缓存),然后通过 iget 获取根目录(rootdir)。
[*]创建 init 进程(1 号进程):调用 newproc() 复制进程,如果成功(返回非零),则扩展用户空间、设置用户段寄存器、将 icode 引导程序复制到进程地址 0 处,然后 return 会跳转到该引导程序,最终执行 /etc/init。
[*]调度循环:如果创建失败,则父进程(0 号进程)进入 sched() 循环,作为系统调度器永远运行。


int icode { ... } 是一个硬编码的引导代码(八进制),它执行 exec("/etc/init") 来启动用户态的管理进程。整个流程就是操作系统从硬件启动到多任务运行的 关键桥梁。

如果你对其中某个细节(如内存分段、时钟检测)有疑问,欢迎继续提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 一份古老的C代码