From 6286d8274f446ac885a9b4897eaff6980f102ade Mon Sep 17 00:00:00 2001 From: hinus Date: Mon, 16 Aug 2021 09:04:07 +0800 Subject: [PATCH] Title: Some system calls: execve, read, write, alarm Issue: https://gitee.com/hinus/linux_kernel_011/issues/I45OEJ Description: Complete some system calls. --- fs/exec.c | 57 ++++++++++++++++++++++++++ kernel/chr_drv/tty_io.c | 89 +++++++++++++++++++++++++++++++---------- kernel/sched.c | 11 +++++ 3 files changed, 135 insertions(+), 22 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index c92e2c0..60df835 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -152,6 +152,7 @@ int do_execve(unsigned long * eip,long tmp,char * filename, argc = count(argv); envc = count(envp); +restart_interp: if (!S_ISREG(inode->i_mode)) { retval = -EACCES; goto exec_error2; @@ -174,7 +175,63 @@ int do_execve(unsigned long * eip,long tmp,char * filename, retval = -EACCES; goto exec_error2; } + ex = *((struct exec *) bh->b_data); + if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) { + char buf[128], *cp, *interp, *i_name, *i_arg; + unsigned long old_fs; + strncpy(buf, bh->b_data+2, 127); + brelse(bh); + iput(inode); + buf[127] = '\0'; + if (cp = strchr(buf, '\n')) { + *cp = '\0'; + for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++); + } + if (!cp || *cp == '\0') { + retval = -ENOEXEC; + goto exec_error1; + } + interp = i_name = cp; + i_arg = 0; + for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) { + if (*cp == '/') + i_name = cp+1; + } + if (*cp) { + *cp++ = '\0'; + i_arg = cp; + } + + if (sh_bang++ == 0) { + p = copy_strings(envc, envp, page, p, 0); + p = copy_strings(--argc, argv+1, page, p, 0); + } + + p = copy_strings(1, &filename, page, p, 1); + argc++; + if (i_arg) { + p = copy_strings(1, &i_arg, page, p, 2); + argc++; + } + p = copy_strings(1, &i_name, page, p, 2); + argc++; + if (!p) { + retval = -ENOMEM; + goto exec_error1; + } + + old_fs = get_fs(); + set_fs(get_ds()); + if (!(inode=namei(interp))) { + set_fs(old_fs); + retval = -ENOENT; + goto exec_error1; + } + set_fs(old_fs); + goto restart_interp; + } + brelse(bh); if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize || ex.a_text+ex.a_data+ex.a_bss>0x3000000 || diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c index 8bda17f..5d6b341 100644 --- a/kernel/chr_drv/tty_io.c +++ b/kernel/chr_drv/tty_io.c @@ -105,12 +105,43 @@ int tty_read(unsigned channel, char * buf, int nr) { tty = tty_table + channel; + if ((current->tty == channel) && (tty->pgrp != current->pgrp)) + return(tty_signal(SIGTTIN, tty)); + + time = 10L*tty->termios.c_cc[VTIME]; + minimum = tty->termios.c_cc[VMIN]; + + if (L_CANON(tty)) { + minimum = nr; + current->timeout = 0xffffffff; + time = 0; + } + else if (minimum) { + current->timeout = 0xffffffff; + } + else { + minimum = nr; + if (time) + current->timeout = time + jiffies; + time = 0; + } + if (minimum>nr) + minimum = nr; + while (nr > 0) { + cli(); if (EMPTY(tty->secondary) || (L_CANON(tty) && !FULL(tty->read_q) && !tty->secondary.data)) { + if (!current->timeout || + (current->signal & ~current->blocked)) { + sti(); + break; + } interruptible_sleep_on(&tty->secondary.proc_list); + sti(); continue; } + sti(); do { GETCH(tty->secondary, c); @@ -127,11 +158,17 @@ int tty_read(unsigned channel, char * buf, int nr) { } } while (nr>0 && !EMPTY(tty->secondary)); - if (L_CANON(tty) && (b - buf)) { + wake_up(&tty->read_q.proc_list); + if (time) + current->timeout = time+jiffies; + if (L_CANON(tty) || b-buf >= minimum) break; - } } + current->timeout = 0; + if ((current->signal & ~current->blocked) && !(b-buf)) + return -ERESTARTSYS; + return (b - buf); } @@ -144,31 +181,39 @@ int tty_write(unsigned channel, char* buf, int nr) { return -1; tty = tty_table + channel; + while (nr > 0) { - c = get_fs_byte(b); - if (O_POST(tty)) { - if (c=='\r' && O_CRNL(tty)) - c = '\n'; - else if (c=='\n' && O_NLRET(tty)) - c = '\r'; - - if (c=='\n' && !cr_flag && O_NLCR(tty)) { - cr_flag = 1; - PUTCH(13,tty->write_q); - continue; - } + sleep_if_full(&tty->write_q); + if (current->signal & ~current->blocked) + break; + + while (nr>0 && !FULL(tty->write_q)) { + c = get_fs_byte(b); + if (O_POST(tty)) { + if (c=='\r' && O_CRNL(tty)) + c = '\n'; + else if (c=='\n' && O_NLRET(tty)) + c = '\r'; + + if (c=='\n' && !cr_flag && O_NLCR(tty)) { + cr_flag = 1; + PUTCH(13,tty->write_q); + continue; + } - if (O_LCUC(tty)) { - c = toupper(c); + if (O_LCUC(tty)) { + c = toupper(c); + } } - } - b++; nr--; - cr_flag = 0; - PUTCH(c,tty->write_q); + b++; nr--; + cr_flag = 0; + PUTCH(c,tty->write_q); + } + tty->write(tty); + if (nr>0) + schedule(); } - - tty->write(tty); return (b-buf); } diff --git a/kernel/sched.c b/kernel/sched.c index c681ad1..e149193 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -49,6 +49,17 @@ void schedule() { if (!(*p)) continue; + if ((*p)->timeout && (*p)->timeout < jiffies) { + (*p)->timeout = 0; + if ((*p)->state == TASK_INTERRUPTIBLE) + (*p)->state = TASK_RUNNING; + } + + if ((*p)->alarm && (*p)->alarm < jiffies) { + (*p)->signal |= (1<<(SIGALRM-1)); + (*p)->alarm = 0; + } + if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) && (*p)->state==TASK_INTERRUPTIBLE) (*p)->state=TASK_RUNNING; -- Gitee