⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 console.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * *//***************************************************************** * simconsole.c * * Very simple console device emulation. * Dan Teodosiu, 07/96 * *****************************************************************/#include <sys/types.h>#include <sys/termios.h>#include <sys/time.h>#include <sys/signal.h>#ifndef linux#include <sys/sysinfo.h>#include <poll.h>#endif#include <sys/times.h>#include <sys/file.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <sys/mman.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <setjmp.h>#include <string.h>#include <memory.h>#include <ctype.h>#include <math.h>#include <stdlib.h>#include <sys/wait.h>#include <sys/socket.h>#include <netdb.h>#include "syslimits.h"#include "simtypes.h"#include "sim_error.h"#include "sim.h"#include "expect.h"#include "checkpoint.h"#include "console.h"#include "machine_params.h"/* * General remarks: * For every console, we have two (logical) interrupt sources: tx and rx * interrupts. These two are OR'ed together inside the device. */typedef struct Sim_Console {  int inited;        /* keeps track of whether this console was inited */  /* interrupt status/enable */  int intr_status;  int intr_enable;  void (*int_f)(int n, int on); /* interrupt function */    /* sconsole connection management */  int in_fd;         /* note: iface 0 uses stdin/stdout */  int out_fd;  int accepter_fd;   /* socket on which we do the accept call */  int accepter_port;  int has_connected;  int warned;        /* failed connection has been reported to error log */  } Sim_Console;/* check whether an int is pending */#define INT_PENDING(sts, enb) (((sts) & (enb)) != 0)/* check whether the intr line has transitioned */#define INT_TRANSITION(old_sts, old_enb, new_sts, new_enb) \    (INT_PENDING(old_sts, old_enb) != INT_PENDING(new_sts, new_enb))static Sim_Console cs[MAX_CONSOLES]; /* console data */static int         ncs;              /* number of consoles */int ConsolePort         = 3456; /* some old port */int SlaveConsoleTimeOut = 600;  /* 10 minutes */extern CptVersion cptVersion;/***************************************************************** * initialization and sconsole session management *****************************************************************//* Make a socket for a slave console (so someone can use 'sconsole' to * connect to it). */static voidCreateConsoleSocket(int n){  struct sockaddr_in sockaddr;  int tmp;  int sfd;    sfd = socket (PF_INET, SOCK_STREAM, 0);  if (sfd < 0) {    perror("Can't open console socket\n");    cs[n].accepter_fd   = -1;    cs[n].accepter_port = -1;    return;  }     /* Allow rapid reuse of this port. */  tmp = 1;  if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp))      < 0) {    perror("CreateConsoleSocket setsockopt SO_REUSEADDR");    /* Not fatal */  }  sockaddr.sin_family      = PF_INET;  sockaddr.sin_port        = htons(ConsolePort + n);  sockaddr.sin_addr.s_addr = INADDR_ANY;  while (bind (sfd, (struct sockaddr *)&sockaddr, sizeof (sockaddr)) || listen (sfd, 1)) {    perror("CreateConsoleSocket - Can't bind address");    Sim_Warning("Console port %d inuse ID %d PID %d\n",		ConsolePort+n, n, getpid());    ConsolePort++;    sockaddr.sin_port = htons(ConsolePort + n);  }    CPUWarning("Console num %d tcp port=%d\n", n, sockaddr.sin_port);  cs[n].accepter_fd   = sfd;  cs[n].accepter_port = sockaddr.sin_port;}/* Open a connection.  This is synchronous and blocks until the sconsole * connection arrives. */static void ConnectSlaveConsole(int n){  struct sockaddr_in sockaddr;  int tmp;  int sock_fd;    int retval;  char buf[256];    tmp = sizeof (sockaddr);  sock_fd  = accept (cs[n].accepter_fd, (struct sockaddr *)&sockaddr, &tmp);  if (sock_fd == -1) {    perror( "ConnectSlaveConsole - Accept failed");    return;  }     /* Tell TCP not to delay small packets.  This greatly speeds up     interactive response. */  tmp = 1;  setsockopt (sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp));  cs[n].in_fd         = sock_fd;  cs[n].out_fd        = sock_fd;  cs[n].has_connected = 1;  sprintf(buf, "\n==== SimOS slave console: Console %d ====\r\n", n);  retval = write(cs[n].out_fd, buf, strlen(buf));  if (retval < 0) {    perror( "ConnectSlaveConsole - Initial output write failed\n");  } else {    Sim_Warning("ConnectSlaveConsole: console %d connected\n", n);  }}/***************************************************************** * ConfigureTerm turns off all character processing by the host OS * so the launched OS can control it. * * We ignore anything except stdin; the sconsole program runs this * same code on the ttys for the slave consoles before connecting. *****************************************************************/static voidConfigureTerm(int fd){#ifdef RESET_TTY  /* I really don't want this for Topsy (PZ) */  struct termios ios;     if ((fd == 0) && isatty(0)) {    if (tcgetattr(fd, &ios) < 0) {      perror( "tcgetattr\n");    }    ios.c_iflag &= ~(ISTRIP|ICRNL|IGNCR|ICRNL|IXOFF|IXON);    ios.c_oflag &= ~OPOST;    ios.c_lflag &= ~(ISIG|ICANON|ECHO);    ios.c_cc[VMIN] = 1;    ios.c_cc[VTIME] = 0;    if (tcsetattr(fd, TCSANOW, &ios) < 0) {      perror( "tcsetattr\n");    }  }#endif}/***************************************************************** * Initialize console. *****************************************************************/static voidInitConsole(int n, void (*int_f)(int n, int on)){   SIMASSERT(!cs[n].inited);   cs[n].inited      = 1;   /* note: intr_status and intr_enable will normally be 0, since    * cs is statically allocated. When restoring from a checkpoint,    * these fields will be set, so don't touch them here.    */   cs[n].int_f       = int_f; /* interrupt function */      if (n == 0) {      /* console 0 gets special treatment since it uses stdin/stdout */      cs[n].in_fd         = 0;      cs[n].out_fd        = 1;      cs[n].has_connected = 1;      cs[n].accepter_fd   = -1;      cs[n].accepter_port = 0;   } else {      CreateConsoleSocket(n);      cs[n].has_connected = 0;      cs[n].in_fd         = cs[n].accepter_fd;      cs[n].out_fd        = -1;   }   cs[n].warned = 0;}/***************************************************************** * Wait for all slave consoles to connect or to time out. *****************************************************************/static voidConsoleWaitLoop(int n){#ifdef linux   /* Only have one console for linux runs for now */  return;#else  int delay     = SlaveConsoleTimeOut;  int connected = 0;  int needed    = n-1;  int i;  struct pollfd fds[MAX_CONSOLES];  Sim_Warning("This configuration calls for %d slave consoles.\n", needed);  Sim_Warning("Use 'sconsole' to connect.  All sessions must start before simulation begins.\n");  Sim_Warning("Any slave consoles not connected within %d seconds will not be usable during this run.\n",	      delay);  Sim_Warning("Waiting for connections...\n");  fds[0].fd = -1;  for (i=1; i<n; i++) {    fds[i].fd      = cs[i].accepter_fd;    fds[i].events  = POLLIN;    fds[i].revents = 0;  }    for (; connected < needed && delay > 0; delay--) {    sleep(1);    if (poll(fds, n, 0) > 0) {      for (i=1; i<n; i++) {        if (fds[i].revents & POLLIN) {	  ConnectSlaveConsole(i);	  fds[i].fd      = -1;   /* ignore on future polls */	  fds[i].revents = 0;	  connected++;        }      }    }  }    if (connected < needed) {    Sim_Warning("\nConsole wait timed out! %d consoles bitbucketed.\n",		needed - connected);  } else {    Sim_Warning("\nAll slave consoles established.\n");  }#endif}      /***************************************************************** * Initialize all consoles  *****************************************************************/voidsim_console_init(int n, void (*int_f)(int n, int on)){  int i;  SIMASSERT(n > 0 && n <= MAX_CONSOLES);  ncs = n;  for (i = 0; i < n; i++) {     InitConsole(i, int_f);  }  if (n > 1) {     ConsoleWaitLoop(n);  }  ConfigureTerm(0); /* need to set line discipline for console 0 */}/***************************************************************** * Poll all console inputs. Should be called periodically. *****************************************************************/static struct {   int hasChar;   char c;} simconsoleSavedChar[MAX_CONSOLES];#ifdef linux/* Linux version of console polling */voidsim_console_poll(void){  fd_set readfds;  int i;  int n;  int old_status;  int max_fd;  struct timeval tv;  tv.tv_sec = 0;  tv.tv_usec = 0;  FD_ZERO(&readfds);  max_fd = 0;  for (i = 0; i < ncs; i++) {     if (cs[i].has_connected != 0) {        FD_SET(cs[i].in_fd, &readfds);	if (cs[i].in_fd >= max_fd) 	  max_fd = cs[i].in_fd;     }  }  n = select(max_fd+1, &readfds, NULL, NULL, &tv);  if (n) {     for(i = 0; i < ncs; i++) {        if (FD_ISSET(cs[i].in_fd, &readfds)) {                      /* post interrupt */           old_status = cs[i].intr_status;           cs[i].intr_status |= CONS_INT_RX;           if (INT_TRANSITION(old_status, cs[i].intr_enable,                              cs[i].intr_status, cs[i].intr_enable) &&               cs[i].int_f)              cs[i].int_f(i, 1); /* 0->1 */        }     }  }}#elsevoidsim_console_poll(void){  static struct pollfd fds[MAX_CONSOLES]; /* must be 0-inited */  int i;  int old_status;    for (i = 0; i < ncs; i++) {    if (cs[i].has_connected != 0) {      fds[i].fd      = cs[i].in_fd;      fds[i].events  = POLLRDNORM;      fds[i].revents = 0;    }  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -