nachos 源码解析,中文注释 main.cc

NachOS 源码在我上传的资源里面,至于安装参见传送门->NachOS安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
// main.cc
//  Driver code to initialize, selftest, and run the
//  operating system kernel.  
//
// Usage: nachos -d <debugflags> -rs <random seed #>
//              -s -x <nachos file> -ci <consoleIn> -co <consoleOut>
//              -f -cp <unix file> <nachos file>
//              -p <nachos file> -r <nachos file> -l -D
//              -n <network reliability> -m <machine id>
//              -z -K -C -N
//
//    -d causes certain debugging messages to be printed (see debug.h)  <debugflags>参数得到不同输出,具体在debug.h
//    -rs causes Yield to occur at random (but repeatable) spots    表示是随机数种子,产生时间片
//    -z prints the copyright message 打印版权信息
//    -s causes user programs to be executed in single-step mode 处于单步模式
//    -x runs a user program    加载用户程序,运行在shell里面
//    -ci specify file for console input (stdin is the default) 指定linux的文件,进行重定向为标准输入
//    -co specify file for console output (stdout is the default) 指定linux的文件,进行重定向为标准输出
//    -n sets the network reliability   设定网络的可靠程度
//    -m sets this machine's host id (needed for the network)   设定nachos内核设定ID,相互通信的进程通过ID进行区别
//    -K run a simple self test of kernel threads and synchronization   开关选项,运行thread库里面test代码,进行内部测试
//    -C run an interactive console test    开关选项,运行console测试
//    -N run a two-machine network test (see Kernel::NetworkTest) 网络测试
//
//    Filesystem-related flags:
//    -f forces the Nachos disk to be formatted
//    -cp copies a file from UNIX to Nachos
//    -p prints a Nachos file to stdout
//    -r removes a Nachos file from the file system
//    -l lists the contents of the Nachos directory
//    -D prints the contents of the entire file system
//
//  Note: the file system flags are not used if the stub filesystem
//        is being used
//
// Copyright (c) 1992-1996 The Regents of the University of California.
// All rights reserved.  See copyright.h for copyright notice and limitation
// of liability and disclaimer of warranty provisions.

#define MAIN
#include "copyright.h"
#undef MAIN

#include "main.h"
#include "filesys.h"
#include "openfile.h"
#include "sysdep.h"

#ifdef TUT

#include "tut.h"
//implements callbacks for unit test
#include "tut_reporter.h"
namespace tut
{
    test_runner_singleton runner;
}

#endif TUT

// global variables
Kernel *kernel;
Debug *debug;


//----------------------------------------------------------------------
// Cleanup
//  Delete kernel data structures; called when user hits "ctl-C".
//----------------------------------------------------------------------

static void
Cleanup(int x)
{    
    cerr << "\nCleaning up after signal " << x << "\n";
    delete kernel;
}

//-------------------------------------------------------------------
// Constant used by "Copy" and "Print"
//   It is the number of bytes read from the Unix file (for Copy)
//   or the Nachos file (for Print) by each read operation
//-------------------------------------------------------------------
static const int TransferSize = 128;


#ifndef FILESYS_STUB
//----------------------------------------------------------------------
// Copy
//      Copy the contents of the UNIX file "from" to the Nachos file "to"
//----------------------------------------------------------------------

static void
Copy(char *from, char *to)
{
    int fd;
    OpenFile* openFile;
    int amountRead, fileLength;
    char *buffer;

// Open UNIX file
    if ((fd = OpenForReadWrite(from,FALSE)) < 0) {      
        printf("Copy: couldn't open input file %s\n", from);
        return;
    }

// Figure out length of UNIX file
    Lseek(fd, 0, 2);            
    fileLength = Tell(fd);
    Lseek(fd, 0, 0);

// Create a Nachos file of the same length
    DEBUG('f', "Copying file " << from << " of size " << fileLength <<  " to file " << to);
    if (!kernel->fileSystem->Create(to, fileLength)) {   // Create Nachos file
        printf("Copy: couldn't create output file %s\n", to);
        Close(fd);
        return;
    }
   
    openFile = kernel->fileSystem->Open(to);
    ASSERT(openFile != NULL);
   
// Copy the data in TransferSize chunks
    buffer = new char[TransferSize];
    while ((amountRead=ReadPartial(fd, buffer, sizeof(char)*TransferSize)) > 0)
        openFile->Write(buffer, amountRead);    
    delete [] buffer;

// Close the UNIX and the Nachos files
    delete openFile;
    Close(fd);
}

#endif // FILESYS_STUB

//----------------------------------------------------------------------
// Print
//      Print the contents of the Nachos file "name".
//----------------------------------------------------------------------

void
Print(char *name)
{
    OpenFile *openFile;    
    int i, amountRead;
    char *buffer;

    if ((openFile = kernel->fileSystem->Open(name)) == NULL) {
        printf("Print: unable to open file %s\n", name);
        return;
    }
   
    buffer = new char[TransferSize];
    while ((amountRead = openFile->Read(buffer, TransferSize)) > 0)
        for (i = 0; i < amountRead; i++)
            printf("%c", buffer[i]);
    delete [] buffer;

    delete openFile;            // close the Nachos file
    return;
}



//----------------------------------------------------------------------
// main
//  Bootstrap the operating system kernel.  
// 
//  Initialize kernel data structures
//  Call some test routines
//  Call "Run" to start an initial user program running
//
//  "argc" is the number of command line arguments (including the name
//      of the command) -- ex: "nachos -d +" -> argc = 3
//  "argv" is an array of strings, one for each command line argument
//      ex: "nachos -d +" -> argv = {"nachos", "-d", "+"}
//----------------------------------------------------------------------

int
main(int argc, char **argv)
{//参数初始化
    int i;
    char *debugArg = "";               //调试信息是否需要打印
    char *userProgName = NULL;        // 运行的用户程序default is not to execute a user prog
    bool threadTestFlag = false;        //线程测试标记
    bool consoleTestFlag = false;       //终端测试标记
    bool networkTestFlag = false;       //网络测试标记
#ifndef FILESYS_STUB                    //如果没有定义自己的文件系统,那么就采用linux文件系统
    char *copyUnixFileName = NULL;    // linux的文件系统 UNIX file to be copied into Nachos
    char *copyNachosFileName = NULL;  // 被复制到nachos里面的文件 name of copied file in Nachos
    char *printFileName = NULL;         //
    char *removeFileName = NULL;
    bool dirListFlag = false;
    bool dumpFlag = false;
#endif //FILESYS_STUB

    // some command line arguments are handled here.    参数解析
    // those that set kernel parameters are handled in
    // the Kernel constructor
    for (i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-d") == 0) {//是否有调试选项
        ASSERT(i + 1 < argc);   // next argument is debug string
            debugArg = argv[i + 1];
        i++;
    }
    else if (strcmp(argv[i], "-z") == 0) {
            cout << copyright << "\n";
    }
    else if (strcmp(argv[i], "-x") == 0) {
        ASSERT(i + 1 < argc);
        userProgName = argv[i + 1];
        i++;
    }
    else if (strcmp(argv[i], "-K") == 0) {
        threadTestFlag = TRUE;
    }
    else if (strcmp(argv[i], "-C") == 0) {
        consoleTestFlag = TRUE;
    }
    else if (strcmp(argv[i], "-N") == 0) {
        networkTestFlag = TRUE;
    }
#ifndef FILESYS_STUB
    else if (strcmp(argv[i], "-cp") == 0) {
        ASSERT(i + 2 < argc);
        copyUnixFileName = argv[i + 1];
        copyNachosFileName = argv[i + 2];
        i += 2;
    }
    else if (strcmp(argv[i], "-p") == 0) {
        ASSERT(i + 1 < argc);
        printFileName = argv[i + 1];
        i++;
    }
    else if (strcmp(argv[i], "-r") == 0) {
        ASSERT(i + 1 < argc);
        removeFileName = argv[i + 1];
        i++;
    }
    else if (strcmp(argv[i], "-l") == 0) {
        dirListFlag = true;
    }
    else if (strcmp(argv[i], "-D") == 0) {
        dumpFlag = true;
    }
#endif //FILESYS_STUB
    else if (strcmp(argv[i], "-u") == 0) {
            cout << "Partial usage: nachos [-z -d debugFlags]\n";
            cout << "Partial usage: nachos [-x programName]\n";
        cout << "Partial usage: nachos [-K] [-C] [-N]\n";
#ifndef FILESYS_STUB
            cout << "Partial usage: nachos [-cp UnixFile NachosFile]\n";
            cout << "Partial usage: nachos [-p fileName] [-r fileName]\n";
            cout << "Partial usage: nachos [-l] [-D]\n";
#endif //FILESYS_STUB
    }

    }
    debug = new Debug(debugArg);
   
    DEBUG(dbgThread, "Entering main");//针对debug,增加调试信息

#ifdef TUT
    ::tut::callback * clbk = new tut::reporter(cout);
    ::tut::runner.get().set_callback(clbk);  
    ::tut::runner.get().run_tests(); //run all unit tests
#endif
    //创建内核对象与初始化
    kernel = new Kernel(argc, argv);//创建虚拟机,主控线程,计算机系统

    kernel->Initialize();//初始化

    CallOnUserAbort(Cleanup);       // if user hits ctl-C

    // at this point, the kernel is ready to do something
    // run some tests, if requested 测试
    if (threadTestFlag) {
      kernel->ThreadSelfTest();  // test threads and synchronization
    }
    if (consoleTestFlag) {
      kernel->ConsoleTest();   // interactive test of the synchronized console
    }
    if (networkTestFlag) {
      kernel->NetworkTest();   // two-machine test of the network
    }

#ifndef FILESYS_STUB//文件系统
    if (removeFileName != NULL) {
      kernel->fileSystem->Remove(removeFileName);
    }
    if (copyUnixFileName != NULL && copyNachosFileName != NULL) {
      Copy(copyUnixFileName,copyNachosFileName);
    }
    if (dumpFlag) {
      kernel->fileSystem->Print();
    }
    if (dirListFlag) {
      kernel->fileSystem->List();
    }
    if (printFileName != NULL) {
      Print(printFileName);
    }
#endif // FILESYS_STUB

    // finally, run an initial user program if requested to do so
    if (userProgName != NULL) {//判断用户名是否为空,通过-x参数传递的
      AddrSpace *space = new AddrSpace;//分配地址空间
      ASSERT(space != (AddrSpace *)NULL);
      if (space->Load(userProgName)) {  // load the program into the space,用户程序加载到这个空间,就绪状态
    space->Execute();              // run the program   运行程序
    ASSERTNOTREACHED();            // Execute never returns 调用终止程序
      }
    }

    // If we don't run a user program, we may get here.
    // Calling "return" would terminate the program.
    // Instead, call Halt, which will first clean up, then
    //  terminate.
    kernel->interrupt->Halt();
   
    ASSERTNOTREACHED();
}