【发布时间】:2020-12-09 17:58:11
【问题描述】:
我有这个练习:
/* smallsh.c */
#include "smallsh.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
char *prompt = "Scrivere un comando>";
void procline(void) /* tratta una riga di input */
{
char *arg[MAXARG+1]; /* array di puntatori per runcommand */
int toktype; /* tipo del simbolo nel comando */
int narg; /* numero di argomenti considerati finora */
int type; /* FOREGROUND o BACKGROUND */
narg=0;
do {
/* mette un simbolo in arg[narg]
ed esegue un'azione a seconda del tipo di simbolo */
switch (toktype = gettok(&arg[narg])) {
case ARG:
/* se argomento: passa al prossimo simbolo */
if (narg < MAXARG) narg++;
break;
case EOL:
case SEMICOLON:
case AMPERSAND:
if(toktype == AMPERSAND) type = BACKGROUND;
else type = FOREGROUND;
/* se fine riga o ';' esegue il comando ora contenuto in arg,
mettendo NULL per indicare la fine degli argomenti:
serve a execvp */
if (narg != 0) {
arg[narg] = NULL;
runcommand(arg, type);
}
/* se non fine riga (descrizione comando finisce con ';')
bisogna ricominciare a riempire arg dall'indice 0 */
if (toktype != EOL) narg = 0;
break;
}
}
while (toktype != EOL); /* fine riga, procline finita */
}
void runcommand(char **cline, int type) /* esegue un comando */
{
pid_t pid;
int exitstat,ret;
pid = fork();
if (pid == (pid_t) -1) {
perror("smallsh: fork fallita");
return;
}
if (pid == (pid_t) 0) { /* processo figlio */
/* esegue il comando il cui nome e' il primo elemento di cline,
passando cline come vettore di argomenti */
//if(type == 1) sleep(2);
execvp(*cline,cline);
perror(*cline);
exit(1);
}
/* non serve "else"... ma bisogna aver capito perche' :-) */
/* qui aspetta sempre e comunque - i comandi in background
richiederebbero un trattamento diverso */
if(type == 1) { //BACKGROUND
/*DO SOMETHING*/
}
else { //FOREGROUND
//PART OF THE ORIGINAL CODE
ret = wait(&exitstat);
if (ret == -1) perror("wait");
}
}
int main()
{
while(userin(prompt) != EOF)
procline();
return 0;
}
/* input.c */
#include "smallsh.h"
/* buffers per la riga di input e la sua segmentazione in "tokens";
puntatori per scorrere i buffers */
static char inpbuf[MAXBUF], tokbuf[2*MAXBUF],
*ptr, *tok;
/* array di caratteri che hanno una interpretazione "speciale"
nei comandi */
static char special[]=
{' ', '\t', ';', '\n', '\0'};
int userin(char *p) /* stampa il prompt e legge una riga */
{
int c, count;
/* inizializzazioni per altre routines */
ptr = inpbuf;
tok = tokbuf;
/* stampa il prompt */
printf("%s ",p);
count=0;
while(1) {
if ((c = getchar()) == EOF)
return(EOF);
/* si copia il carattere letto in inpbuf; ma se si raggiunge
e supera MAXBUF, non si scrive piu' in inpbuf,
si continua a leggere fino a newline (si veda sotto) */
if (count < MAXBUF)
inpbuf[count++] = c;
/* se si legge il newline, la riga in input e' finita */
if (c == '\n' && count < MAXBUF) {
inpbuf[count] = '\0';
return(count);
}
/* se e' stato superato MAXBUF, quando si arriva al newline
si avverte che la riga e' troppo lunga e si
va a leggere una nuova riga */
if (c == '\n') { /* implicito se si arriva qui: count >= MAXBUF */
printf("riga in input troppo lunga\n");
count = 0;
printf("%s ",p);
}
}
}
int gettok(char **outptr) /* legge un simbolo e lo mette in tokbuf */
{
int type;
/* si piazza *outptr in modo che punti al primo byte dove si cominicera'
a scrivere il simbolo letto */
*outptr = tok;
/* salta eventuali spazi */
while (*ptr == ' ' || *ptr == '\t') ptr++;
/* copia il primo carattere del simbolo */
*tok++ = *ptr;
/* a seconda del carattere decide il tipo di simbolo */
switch(*ptr++){
case '\n':
type = EOL; break;
case ';':
type = SEMICOLON; break;
case '&':
type = AMPERSAND; break;
default:
type = ARG;
/* copia gli altri caratteri del simbolo */
while(inarg(*ptr))
*tok++ = *ptr++;
}
/* aggiunge \0 al fondo */
*tok++ = '\0';
return(type);
}
int inarg(char c) /* verifica se c non e' un carattere speciale */
{
char *wrk;
for (wrk = special; *wrk != '\0'; wrk++)
if (c == *wrk) return(0);
return(1);
}
/* smallsh.h */
#define FOREGROUND 0
#define BACKGROUND 1
#define MAXARG 512 /* numero massimo di argomenti */
#define MAXBUF 512 /* lunghezza massima riga di input */
int inarg(char c); /* verifica se c non e' un carattere speciale */
int userin(char *p); /* stampa il prompt e legge una riga */
int gettok(char **outptr); /* legge un simbolo */
void procline(); /* tratta una riga di input */
void runcommand(char **cline, int type); /* esegue un comando */
我必须实现一个后台执行 (&) 但我不知道如何...
我尝试在前台执行时使用等待,而在后台执行时不使用,但提示符和命令输出在同一行,并且“光标”在新行上。
可以得到这样的结果:
命令> ls &
//输出
Command> //光标在这里
代替:
命令> ls &
命令> //输出
//光标在这里
?
【问题讨论】:
-
在后台运行进程的全部意义在于它在 shell 继续运行更多内容的同时运行。因此,根据定义,如果后台命令产生输出,它将与 shell(和其他命令)的输出混合。这就是为什么后台进程通常总是将其 stdin/stdout/stderr 重定向。