终端控制和和信号——《Unix/Linux编程实践教程》读书笔记(第6章)

1、有些程序处理从特定设备来的数据。这些与特定设备相关的程序必须控制与设备的连接。Unix系统中最常见的设备是终端。

2、终端驱动程序有很多设置。各个设置的特定值决定了终端驱动程序的模式。为用户编写的程序通常需要设置终端驱动程序为特定的模式。

3、键盘输入分为3类,终端驱动程序对这些输入做不同的处理。大多数建代表常规数据,它们从驱动程序传输到程序。有些键调用驱动程序中的编辑函数。如果按下删除键,驱动程序将前一个字符从它的行缓冲中删除,并将命令发送到终端屏幕,使之从显示器中删除字符。最后,有些键调用处理控制函数。Ctrl-C键告诉驱动程序调用内核中某个函数,这个函数给进程发送一个信号。终端驱动程序支持若干种处理控制函数,它们都通过发送信号到进程来实现控制。

man 2 signal

4、信号是从内核发送给进程的一种简短消息。信号可能来自用户、其他进程或内核本身。进程可以告诉内涵,在它收到信号时需要做出怎样的响应。

5、

man 2 fcntl
#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */);

6、

man 2 signal
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
    /*
     * signal() returns the previous value of the signal handler,
     * or SIG_ERR on error. In the event of an error,
     * errno is set to indicate the cause.
     */

7、

/*
 * play_aganin04.c
 * purpose: ask if user wants another transaction
 * method: set tty into char-by-char mode and no echo mode,
 *         set tty into no-delay mode
 *         read char, return result
 *         resets terminal modes on SIGINT, ignores SIGQUIT
 * returns: 0->yes, 1->no, 2->timeout
 * better: reset terminal mode on Interrupt
 */

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>

#define ASK "Do you want another transaction"
#define TRIES (3)           /* max tries */
#define SLEEPTIME (2)       /* time per try */
#define BEEP putchar(‘\a‘)  /* alert user */

int get_response(char *, int);
char get_ok_char(void);
void tty_mode(int);
//void set_crmode(void);
void set_cr_noecho_mode(void);
void set_nodelay_mode(void);

int main(void)
{
    int response;
    void ctrl_c_handler(int);

    tty_mode(0);                    /* save tty mode */
    //set_crmode();                 /* set char-by-char mode */
    set_cr_noecho_mode();
    set_nodelay_mode();
    signal(SIGINT, ctrl_c_handler); /* handle INT */
    signal(SIGQUIT, SIG_IGN);       /* ignore QUIT signals */
    response = get_response(ASK, TRIES);
    tty_mode(1);                    /* restore tty mode */
    printf("\n");
    return response;
}

int get_response(char *question, int maxtries)
/*
 * purpose: ask a question and wait for a y/n answer or maxtries
 * method: use a getchar and ignore non y/n answers
 * returns: 0->yes, 1->no
 */
{
    int input;

    printf("%s (y/n)?", question);
    fflush(stdout);
    while (1)
    {
        sleep(SLEEPTIME);
        input = tolower(get_ok_char());
        if (input == ‘y‘)
            return 0;
        if (input == ‘n‘)
            return 1;
        if (maxtries-- == 0)
            return 2;
        BEEP;
    }
}

/*
 * skip over non-legal chars and return y, Y, n, N or EOF
 */
char get_ok_char(void)
{
    char c;
    while ((c = getchar()) != EOF && strchr("yYnN", c) == NULL)
        ;
    return c;
}

void set_cr_noecho_mode(void)
/*
 * purpose: put file descriptor 0 into char-by-char and noecho mode
 * method: use bits in termios
 */
{
    struct termios ttystate;

    tcgetattr(0, &ttystate);
    ttystate.c_lflag &= ~ICANON;        /* no buffering */
    ttystate.c_lflag &= ~ECHO;          /* no echo either */
    ttystate.c_cc[VMIN] = 1;            /* get 1 char at a time */
    tcsetattr(0, TCSANOW, &ttystate);   /* install settings */
}

void set_nodelay_mode(void)
/*
 * purpose: put file descriptor 0 into no_delay mode
 * method: use fcntl to set bits
 * notes: tcsetattr() will do something similar, but it is complicated
 */
{
    int termflags;
    termflags = fcntl(0, F_GETFL);      /* read curr settings */
    termflags |= O_NDELAY;              /* flip on nodelay bit */
    fcntl(0, F_SETFL, termflags);       /* and install them */
}

/* how == 0 -> save current mode, how == 1 -> restore mode */
/* this version handles termios and fcntl flags */
void tty_mode(int how)
{
    static struct termios original_mode;
    static int original_flags;
    static int stored = 0;
    if (how == 0)
    {
        tcgetattr(0, &original_mode);
        original_flags = fcntl(0, F_GETFL);
        stored = 1;
    }
    else
    {
        tcsetattr(0, TCSANOW, &original_mode);
        fcntl(0, F_SETFL, original_flags);
    }
}

void ctrl_c_handler(int signum)
/*
 * purpose: called if SIGINT is detected
 * action: reset tty and scram
 */
{
    tty_mode(1);
    printf("\nCtrl-C pressed.\n");
    exit(1);
}

终端控制和和信号——《Unix/Linux编程实践教程》读书笔记(第6章)

时间: 2024-12-24 21:01:08

终端控制和和信号——《Unix/Linux编程实践教程》读书笔记(第6章)的相关文章

进程和程序:编写shell——《Unix/Linux编程实践教程》读书笔记(第8章)

1.Unix shell的功能 shell是一个管理进程和运行程序的程序.所有常用的shell都有3个主要功能: (1)运行程序: (2)管理输入和输出 (3)可编程 shell同时也是带有变量和流程控制的编程语言. 2.Unix的进程模型 一个程序是存储在文件中的机器指令序列,一般它是由编译器将源代码编译成二进制格式的代码.运行一个程序意味着将这些机器指令序列载入内存然后让处理器(CPU)逐条执行.在Unix术语中,一个可执行程序是一些机器指令机器数据的序列.一个进程是程序运行时的内存空间和设

事件驱动编程——《Unix/Linux编程实践教程》读书笔记(第7章)

1.curses库 /* 基本curses函数 */ initscr(); // 初始化curses库和tty endwin(); // 关闭curses并重置tty refresh(); // 使屏幕按照你的意图显示 move(r, c); // 移动光标到屏幕的(r, c)位置 addstr(s); // 在当前位置画字符串s addch(c); // 在当前位置画字符c clear(); // 清屏 standout(); // 启动standout模式(一般使屏幕反色) standend

I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)

1.I/O重定向的概念与原因 及 标准输入.输出的标准错误的定义 所以的Unix I/O重定向都基于标准数据流的原理.三个数据了分别如下: 1)标准输入--需要处理的数据流 2)标准输出--结果数据流 3)标准错误输出--错误消息流 概念:所以的Unix工具都使用文件描述符0.1和2.标准输入文件的描述符是0,标准输出的文件描述符是1,而标准错误输出的文件描述符则是2.Unix假设文件描述符0.1.2已经被打开,可以分别进行读写操作. 通常通过shell命令行运行Unix系统工具时,stdin.

系统调用操作文件——《Unix/Linux编程实践教程》读书笔记

1.who命令通过读系统日志的内容显示当前已经登录的用户. 2.Unix系统把数据存放在文件中,可以通过以下系统调用操作文件: open(filename, how) creat(filename, mode) read(fd, buffer, amt) write(fd, buffer, amt) lseek(fd, distance, base) close(fd) 3.进程对文件的读/写都要通过文件描述符,文件描述符表示文件和进程之间的连接. 4.每次系统调用都会导致用户模式和内核模式的切

目录与文件属性——《Unix/Linux编程实践教程》读书笔记

1.ls产生一个文件名的列表,它大致是这样工作的: open directory +-> read entry - end of dir? -+ |__ display file info | close directory <--------------+ 2.目录是一种特殊的文件,它的内容是文件和目录的名字.与普通文件不同的是,目录文件永远不会空,每个目录至少包含2个特殊的项,即 "."和"..",其中 "."不是当前目录,&qu

Unix/Linux编程实践教程

execvp在程序中启动新程序: 用fork创建新进程: forkdemo2代码: 测试fork的时候参考<Linux权威指南>阅读笔记(3)  使用了patch: [[email protected] programming]# diff -c forkdemo2.c forkdemo2_new.c > forkdemo2.patch [[email protected] programming]# patch < forkdemo2.patch patching file fo

Unix/Linux编程实践教程(0:)

本来只打算读这本书socket等相关内容,但书写得实在好,还是决定把其余的内容都读一下. 阅读联机帮助的一个示例: open系统调用: read系统调用: Unix的time: 上面的printf可以看到,一个临时的char* 指针也可以+4,希望查看ctime函数里面是否有malloc,如果有的话由谁来释放内存???没有的话为什么可以指针操作. 为解决上述疑惑,通过查看http://www.cplusplus.com/reference/ctime/ctime/以及及http://www.cp

Unix/Linux编程实践教程(三:代码、测试)

测试logfilec.c的时候,有个sendto(sock,msg,strlen(msg),0,&addr,addrlen),编译时提示: logfilec.c:30: warning: passing argument 5 of ‘sendto’ from incompatible pointer type 但是书上是这样写的,在stackoverflow搜了一下,原来是: 需要进行一个转换.

《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h>文件中的常量. 通过cat 命令查看: [email protected]:~/Code/tlpi$ cat /usr/include/limits.h /* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 Free Software