Follow MIT的6.828 Lab1 & Homework:shell

本文介绍了MIT 6.828操作系统课程中Shell作业的具体实现细节,包括如何处理简单命令如ls,解析命令行参数,以及如何使用C语言API进行开发。

其实环境还是没装好来着,先跟着作业做一下。。。

第一个作业:Shell

https://pdos.csail.mit.edu/6.828/2014/homework/xv6-shell.html

implementing several features in a small shell, which we will refer to as the 6.828 shell

要求:

Implement simple commands, such as:
$ ls

The parser already builds an execcmd for you, so the only code you have to write is for the ’ ’ case in runcmd. You might find it useful to look at the manual page for exec; type “man 3 exec”, and read about execv. Print an error message when exec fails.

这里写图片描述

看代码

查询C语言API:
IBN Knowledge Center(好高大上的样子)

main

int
main(void)
{
  static char buf[100];
  int fd, r;

  // Read and run input commands.
  while(getcmd(buf, sizeof(buf)) >= 0){ // 简单的判断用户输入是否为空
    if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
      // Clumsy but will have to do for now.
      // Chdir has no effect on the parent if run in the child.
      // chdir : 切换到目标工作目录
      buf[strlen(buf)-1] = 0;  // chop \n
      if(chdir(buf+3) < 0) // 切换失败(chdir返回-1)
        fprintf(stderr, "cannot cd %s\n", buf+3);
      continue;
    }
    if(fork1() == 0) // 创建成功(fork1()返回0)
      runcmd(parsecmd(buf));
    wait(&r); //wait() — Wait for a child process to end
  }
  exit(0);
}

parsecmd

struct cmd* parsecmd(char *s)
{ // s: 指向缓冲区的指针
  char *es;
  struct cmd *cmd;

  es = s + strlen(s); // es指向缓冲区最后一个字符
  cmd = parseline(&s, es);  //parseline:将字符串转换为结构体'cmd'
  peek(&s, es, ""); // 
  if(s != es){ 
    fprintf(stderr, "leftovers: %s\n", s);
    exit(-1);
  }
  return cmd;
}

runcmd

void runcmd(struct cmd *cmd)
// Execute cmd.  Never returns.
{
  int p[2], r;
  struct execcmd *ecmd;
  struct pipecmd *pcmd;
  struct redircmd *rcmd;

  if(cmd == 0) // 保护:命令为空返回
    exit(0);

  switch(cmd->type){
  default:
    fprintf(stderr, "unknown runcmd\n");
    exit(-1);

  case ' ':
    ecmd = (struct execcmd*)cmd;
    if(ecmd->argv[0] == 0)
      exit(0);
    fprintf(stderr, "exec not implemented\n");
    // Your code here ...
    break;

  case '>':
  case '<':
    rcmd = (struct redircmd*)cmd;
    fprintf(stderr, "redir not implemented\n");
    // Your code here ...
    runcmd(rcmd->cmd);
    break;

  case '|':
    pcmd = (struct pipecmd*)cmd;
    fprintf(stderr, "pipe not implemented\n");
    // Your code here ...
    break;
  }    
  exit(0);
}

getcmd

int getcmd(char *buf, int nbuf)
{

  if (isatty(fileno(stdin))) // 不知道为什么是stdin,
    fprintf(stdout, "6.828$ "); // 反正结果是不断输出prompt..
  memset(buf, 0, nbuf); // 清空缓存
  fgets(buf, nbuf, stdin); // 得到输入
  if(buf[0] == 0) // EOF
    return -1;
  return 0;
}

用到的API

strrchr() — Find Last Occurrence of Character in String,

Returns a pointer to the last occurrence of c in string.

A built-in function that finds the last occurrence of c (converted to a char) in string. The ending null character is considered part of the string.

fileno()

fileno() — Get the file descriptor from an open stream
Returned value
If successful, fileno() returns the file descriptor number associated with an open HFS stream (that is, one opened with fopen() or freopen()).

isatty() - Test if descriptor represents a terminal

Format

#define _POSIX_SOURCE
#include <unistd.h>

int isatty(int fildes);

Returned value
isatty() returns 1 if the given file descriptor is a terminal, or 0 otherwise.

fgets() — Read a string from a stream

char *fgets(char * __restrict__string, int n, FILE * __restrict__stream);

Reads bytes from a stream pointed to by stream into an array pointed to by string, starting at the position indicated by the file position indicator.
Reading continues until the number of characters read is equal to n-1, or until a newline character (\n), or until the end of the stream, whichever comes first. The fgets() function stores the result in string and adds a NULL character (\0) to the end of the string. The string includes the newline character, if read.
Returned value
If successful, fgets() returns a pointer to the string buffer.
If unsuccessful, fgets() returns NULL to indicate failure.

写代码

看着看着代码发现嵌套好多,而且其实没必要弄懂每个函数在干嘛,因为其实只需要补全

// Execute cmd.  Never returns.
void  runcmd(struct cmd *cmd)
{
...
  case ' ':
    ecmd = (struct execcmd*)cmd;
    if(ecmd->argv[0] == 0)
      exit(0);
    fprintf(stdout, "building...%s\n",ecmd->argv[0]);
    // Your code here ...
    execution(ecmd->argv[0]);
    break;

  case '>':
  case '<':
    rcmd = (struct redircmd*)cmd;
    fprintf(stderr, "redir not implemented\n");
    // Your code here ...
    runcmd(rcmd->cmd);
    break;

  case '|':
    pcmd = (struct pipecmd*)cmd;
    fprintf(stderr, "pipe not implemented\n");
    // Your code here ...
    break;
  }    
  exit(0);
}

编写

void execution(char* exccmd) {

    if (strcmp(exccmd, "ls")==0) {
    // ls : 列出当前目录下所有文件名
     char current_address[100];  
    memset(current_address, 0, 100);  
    getcwd(current_address, 100); //获取当前路径  
    strcat(current_address, "\\*");  
    /*

    还没写完

    */
    }
}

要用到的API

_findfirst

intptr_t _findfirst(  
   const char *filespec,  
   struct _finddata_t *fileinfo   
); 

Parameters
filespec
Target file specification (can include wildcard characters).
fileinfo
File information buffer.
Return Value
If successful, _findfirst returns a unique search handle identifying the file or group of files that match the filespec specification, which can be used in a subsequent call to _findnext or to _findclose. Otherwise, _findfirst returns –1 and sets errno to one of the following values.

&lt;think&gt;Okay, the user is presenting an error message related to Jetpack Compose&#39;s Text function and asking what the problem is. Hmm, the error clearly states that none of the provided Text function signatures are applicable. Looking at the two signatures, one takes AnnotatedString while the other takes String. This suggests the user might be passing an incorrect data type to the text parameter. I notice both signatures have many optional parameters with default values, which means the issue likely isn&#39;t with modifier or styling arguments. The core problem must be the text argument type mismatch. The user seems to be working with Jetpack Compose and encountering a common compile-time error. They probably copied some code without noticing the text type requirement. I should explain this clearly and suggest checking the variable type. Considering related questions: users facing this error might wonder about converting between String and AnnotatedString, or troubleshoot styling issues. They might also confuse this with other Compose errors. Good to include these as follow-up questions. Better keep the explanation concise but actionable. The solution is straightforward - just ensure the text parameter matches either String or AnnotatedString. Should mention both explicit conversion methods (AnnotatedString.Builder or toString()) for completeness. &lt;/think&gt;这个问题是 **Jetpack Compose 的 `Text` 函数调用签名不匹配错误**。以下是关键分析: 1. **错误本质** 编译器提示两个 `Text` 函数均不适用,说明传入的 `text` 参数类型与函数声明不匹配: - 第一个函数要求 `text: AnnotatedString` - 第二个函数要求 `text: String` 2. **常见原因** - 传入的文本变量既非 `String` 也非 `AnnotatedString`(例如可能是 `CharSequence` 或自定义类型) - 使用了空值(如 `null`)作为文本参数 - 未正确处理跨平台代码中的文本类型差异 3. **解决方案** ```kotlin // 方案1:明确转换为String Text(text = yourVariable.toString()) // 方案2:构建AnnotatedString Text(text = buildAnnotatedString { append(yourText) }) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值