Chinaunix首页 | 论坛 | 博客
  • 博客访问: 34380
  • 博文数量: 12
  • 博客积分: 460
  • 博客等级: 下士
  • 技术积分: 125
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-18 14:19
文章分类

全部博文(12)

文章存档

2010年(12)

我的朋友
最近访客

分类: LINUX

2010-02-19 23:35:05

P18: 在VT100终端上反白显示
     printf("\033[7more?\033[m");

P21: 打开键盘,读取键盘输入。无论输入是标准输入还是被重定向到其他文件,都从键盘接受按键输入。
    FILE * fp_tty;
    fp_tty=fopen("/dev/tty","r");
    while((c=getc(fp_tty)!=EOF)
    {
       if(c=='q')
          ......
    }

P29: 已登录用户的信息是放在/var/adm/utmp中,数据结构包含在

P33: man -k keyword  查找带有“keyword”的联机文档. 在其中进一步查找含有read的文档的方法是 man -k keyword | grep read

P58: 处理系统调用中的错误
    内核通过全局变量errno来记录当前系统调用的错误代码。错误代码定义在中,可以直接调用perror()来打印对应的系统出错信息.
    处理errno 的例子
    #include
    extern int errno;
    ....
    int fd = open("file",O_RDONLY);
    if(fd == -1)
    {
       if(errno == ENOENT)
          printf("There is no such file\n");
       else if(errno == EINTR)
       .....
    }

   而使用perror的例子
    int fd = open("file",O_RDONLY);
    if(fd == -1)
    {
       perror("Can not open file");
    }


P68: 目录操作有关函数 opendir(), readdir_r(),telldir(),seekdir(), rewinddir(), closedir()

P73: 获取文件信息的系统调用 state()

P157:终端模式小结:
     1 规范模式。驱动程序输入的字符保存在缓冲区,并且仅在接受到回车键时才将这些缓冲的字符发送到程序。
    2 非规范模式。当缓冲和编辑被关闭是,连接被称为处于非规范模式。
    3 raw 模式。每个处理步骤被当作一个独立的为控制。
    可以用stty 命令来设置终端的状态。
    stty -icanon; 关闭规范模式,输入直接被驱动程序发送到程序
    或者在程序中调用
    set_crmode()
    {
       struct termios ttystate;
       tcgetattr(0,&ttystate);      // read curr. setting
       ttystate.c_lflag &= ~ICANON; // no buffer
       ttystate.c_cc[VMIN]  = 1;    // read one char at a time
       tcsetattr(0, TCSANOW, &ttystate); // install setting
    }

P163: 阻塞与非阻塞输入。 阻塞不仅仅是终端链接的特性,而是任何一个打开的文件的属性。程序可以使用fcntl或者open吧文件描述符启动为非阻塞(noneblick input)。如果文件描述符设置了O_NDELAY位,并且那块空间是空的,read调用返回0.
      set_nodelay_mode()
    {
       int termflags;
       termflags |= O_NODELAY;
       fcntl(0,F_SETEL,termflags); // 把标准输入设置成none delay mode
    }

   
P203: 信号处理 sigaction
    PISIX标准。
    int sigaction(signalnumber, action, prevaction);

    struct sigaction{
       void (* sa_handler)();  /* SIG_DFL, SIG_IGN, or function */
       void (* sa_sigaction)(int, siginfo_t *, void *); /* new handler */
       sigset_t sa_mask;      /* signals to block while handling */
       int sa_flags;          /* enable various behaviors */
    }

    sa_flags :
     SA_RESETHAND   当处理函数被调用时重置信号的处理函数为系统默认处理函数,也就是采用捕鼠器模式
     SA_NODEFER     在处理信号时关闭信号的自动阻塞。这样允许递归调用。
     SA_RESTART     当系统调用是针对一些慢速的设备或类似的系统调用,重新开始,而不是返回。采用BSD模式
     SA_SIGINFO     位被设置上的时候, 内核使用sa_handler作为信号的处理函数. sa_handler 是类似于signal()的处理方法,只能获得捕获信号的编号. 如果该位没有被置上,则使用sa_sigaction做为信号的处理函数,在这种情况下内核传递给函数的不仅是信号编号,还包括了指向描述信号产生原因和条件的结构体.
    在Fedora7上测试,发现无论 SA_SIGINFO是否被设置,只要sa_sigaction被连接上,都会执行sa_sigaction指定的函数。

    如果希望在调用系统的默认处理函数之前做点什么事情,可以使用SA_RESETHAND注册一个函数,在改函数中完成你所希望的事情,然后再重新发送这个信号。

测试代码如下

#include
#include
#define INPUTLEN 100

main()
{
        struct sigaction newhandler;
        sigset_t blocked;
        void inthandler();
        void intsignalaction(int s, siginfo_t * pinof, void * p);
        char x[INPUTLEN];
        char readback=0;
        printf("1 to use sa_handler\n2 to use sa_sigaction(default)\nyou input:");
        readback = getchar();
        if(readback == '1')
        {
            printf("use SA_RESETHAND | SA_RESTART\n");
            newhandler.sa_flags = SA_RESETHAND | SA_RESTART;
        }
        else
        {
            printf("n = %x%c\n",readback,readback);
            printf("use SA_RESETHAND | SA_RESTART | SA_SIGINFO\n");
            newhandler.sa_flags = SA_RESETHAND | SA_RESTART | SA_SIGINFO;
        }
        /* load these two members first */
        newhandler.sa_handler = inthandler;
//        newhandler.sa_sigaction = intsignalaction;
        sigemptyset(&blocked);
        sigaddset(&blocked, SIGQUIT);
        newhandler.sa_mask = blocked;
        printf("newhandler.sa_flags=%x\n", newhandler.sa_flags);
        if(sigaction(SIGINT, &newhandler, NULL) == -1)
            perror("sigaction");
        else
            while(1){
                    fgets(x, INPUTLEN, stdin);
                    printf("main loop input: %s",x);
            }   
}

void inthandler(int s)
{
        printf("inthandler Called with signal %d\n",s);
        sleep(s);
        printf("done handling signal %d\n",s);
}


#if 0
   siginfo_t {
                  int      si_signo;  /* Signal number */
                  int      si_errno;  /* An errno value */
                  int      si_code;   /* Signal code */
                  pid_t    si_pid;    /* Sending process ID */
                  uid_t    si_uid;    /* Real user ID of sending process */
                  int      si_status; /* Exit value or signal */
                  clock_t  si_utime;  /* User time consumed */
                  clock_t  si_stime;  /* System time consumed */
                  sigval_t si_value;  /* Signal value */
                  int      si_int;    /* POSIX.1b signal */
                  void *   si_ptr;    /* POSIX.1b signal */
                  void *   si_addr;   /* Memory location which caused fault */
                  int      si_band;   /* Band event */
                  int      si_fd;     /* File descriptor */
              }
#endif

void siginfo_t_dump(siginfo_t * pinof)
{
    printf("si_signo = %d\n", pinof->si_signo);
    printf("si_errno = %d\n", pinof->si_errno);
/*    printf("si_code = %d\n", pinof->si_code);
    printf("si_pid = %d\n", pinof->si_pid);
    printf("si_uid = %d\n", pinof->si_uid);
    printf("si_status = %d\n", pinof->si_status);
    printf("si_utime = %d\n", pinof->si_utime);
    printf("si_stime = %d\n", pinof->si_stime);
    printf("si_value = %d\n", pinof->si_value);
    printf("si_int = %d\n", pinof->si_int);
    printf("si_ptr = %d\n", pinof->si_ptr);
    printf("si_addr = %d\n", pinof->si_addr);
    printf("si_band = %d\n", pinof->si_band);
    printf("si_fd = %d\n", pinof->si_fd);
*/
}



void intsignalaction(int s, siginfo_t * pinof, void * p)
{
        printf("intsignalaction Called with signal %d\n",s);
//        siginfo_t_dump(pinof);
        sleep(2);
        printf("done handling signal %d\n",s);
}

P218 使用异步IO
    方法一 使用O_ASYNC
    使用fcntl的F_SETOWN命令来告诉内核发送输入通知信号给进程
    通过调用fcntl来设置文件描述符0的O_ASYNC位来打开输入信号。当有一个从键盘来的字符到达,内核向进程发送SIGIO信号. SIGIO的处理函数使用标准curses函数来读入这个字符。红色为相关代码。注意set_ticker()可能是从curser库里头拿掉了,需要自己实现
#include
#include
#include
#include
#include

#define MESSAGE "hello"
#define BLANK   "     "

int row  = 10;
int col =0;
int dir = 1;
int delay = 200;
int done = 0;
main()
{
    void on_alarm(int);
    void on_input(int);
    void enable_kdb_signals();
    initscr();
    crmode();
    noecho();
    clear();
   
    signal(SIGIO,on_input);
    enable_kdb_signals();
    signal(SIGALRM, on_alarm);
    set_ticker(delay);
    move(row,col);
    addstr(MESSAGE);
    while(!done)
        pause();
    endwin();
}

void on_input(int signum)
{
    int c = getch();
    if(c== 'Q' || c==EOF)
      done = 1;
    else if(c==' ')
        dir = -dir;
       
}

void on_alarm(int signum)
{
    signal(SIGALRM, on_alarm);
    mvaddstr(row, col, BLANK);
    col+=dir;
    mvaddstr(row, col, MESSAGE);
    refresh();
   
    if(dir == -1 && col <= 0)
        dir = 1;
    else if(dir == 1 && col + strlen(MESSAGE)>=COLS)
        dir =  -1;
}

void enable_kdb_signals()
{
    int fd_flags;
    fcntl(0, F_SETOWN, getpid());
    fd_flags=fcntl(0, F_GETFL);
    fcntl(0,F_SETFL,(fd_flags | O_ASYNC));
}

int set_ticker(int n_msecs)
{
    struct itimerval new_timeset;
    long n_sec,n_usecs;

    n_sec = n_msecs/1000;
    n_usecs=(n_msecs%1000)*1000L;
   
    new_timeset.it_interval.tv_sec=n_sec;
    new_timeset.it_interval.tv_usec=n_usecs;
   
    new_timeset.it_value.tv_sec = n_sec;
    new_timeset.it_value.tv_usec= n_usecs;
   
    return setitimer(ITIMER_REAL,&new_timeset,NULL);
}

P221    方法二 使用aio_read
    1. 设置输入被读入时候的处理函数on_input
    2. 设置 kbcbuf中的变量来指明等待什么类型的输入,当输入是产生什么信号。这里在读取按键输入的时候产生一个SIGIO信号,我们在注册了SIGIO信号的处理函数以后把在处理函数中读取kbcbuf中的数据.
    3. aio_read不会阻塞程序,而是在完成以后给系统发信号。
    注意1. aio_read 在librt里头,需要在编译是指定。 2. 通过实践,似乎这种方法的响应速度比较慢(个人感觉)
    如下是代码,相关代码为红色
//bounce_aio.c
#include
#include
#include
#include
#include
#include

#define MESSAGE "hello"
#define BLANK   "     "

int row  = 10;
int col =0;
int dir = 1;
int delay = 200;
int done = 0;
static struct aiocb kbcbuf;

main()
{
    void on_alarm(int);
    void on_input(int);
    void setup_aio_buffer();
   
    initscr();
    crmode();
    noecho();
    clear();
   
    signal(SIGIO,on_input);
    setup_aio_buffer();
    aio_read(&kbcbuf);// request for the first round read key
    signal(SIGALRM, on_alarm);
    set_ticker(delay);
    move(row,col);
    addstr(MESSAGE);
    while(!done)
        pause();
    endwin();
}

void on_input(int signum)
{
    int c;
    char * cp = (char *)kbcbuf.aio_buf;
    if(aio_error(&kbcbuf)!=0)
        perror("reading failed!");
    else
        if(aio_return(&kbcbuf) == 1)
        {
                c = *cp;
                if(c=='Q' || c=='q' || c == EOF)
                    done = 1;
                else if(c == ' ')
                    dir = -dir;
        }
    aio_read(&kbcbuf);  //request for next round read key board
}

void on_alarm(int signum)
{
    signal(SIGALRM, on_alarm);
    mvaddstr(row, col, BLANK);
    col+=dir;
    mvaddstr(row, col, MESSAGE);
    refresh();
   
    if(dir == -1 && col <= 0)
        dir = 1;
    else if(dir == 1 && col + strlen(MESSAGE)>=COLS)
        dir =  -1;
}

void setup_aio_buffer()
{
    static char input[1];
    kbcbuf.aio_fildes=0;
    kbcbuf.aio_buf = input;
    kbcbuf.aio_nbytes = 1;
    kbcbuf.aio_offset = 0;
    kbcbuf.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    kbcbuf.aio_sigevent.sigev_signo = SIGIO; /* SEND SIGIO */
}

int set_ticker(int n_msecs)
{
    struct itimerval new_timeset;
    long n_sec,n_usecs;

    n_sec = n_msecs/1000;
    n_usecs=(n_msecs%1000)*1000L;
   
    new_timeset.it_interval.tv_sec=n_sec;
    new_timeset.it_interval.tv_usec=n_usecs;
   
    new_timeset.it_value.tv_sec = n_sec;
    new_timeset.it_value.tv_usec= n_usecs;
   
    return setitimer(ITIMER_REAL,&new_timeset,NULL);
}


P285 在C程序中读取环境变量
    #include
    char * cp = getevn("LANG")






   
阅读(1275) | 评论(0) | 转发(0) |
0

上一篇:linux c/c++ GDB教程详解

下一篇:2.6 内核编译

给主人留下些什么吧!~~