0

我有一个系统调用读取,如下所示:

ssize_t serp_read(struct file *filep, char __user *buf, size_t count, loff_t *offp){
        ssize_t cnt;
        char *buffer;
        int i;

        buffer = kmalloc(count * sizeof(char), GFP_KERNEL);

        for (i = 0; i != count; ++i) {
            buffer[i] = UART_read();
            if(buffer[i] == '\n')
                break;
        }

        cnt = copy_to_user(buf, buffer, i);
        kfree(buffer);
        if(cnt) {
        printk("Error in copy_to_user() cnt is %d\n", cnt);
        i -= cnt; /* bytes successfully copied */
        }

        return i; 
}

而 UART_read() 是

unsigned char UART_read(void){
     unsigned int buf;
     if( ( inb(UART + UART_LSR) & UART_LSR_FE ) == 1){
       printk("KERNEL - Framing error"); return -1;}
     else if( ( inb(UART + UART_LSR) & UART_LSR_PE ) == 1){
       printk("KERNEL - Parity error"); return -1;}
     else if( ( inb(UART + UART_LSR) & UART_LSR_OE ) == 1){
       printk("KERNEL - Overrun error"); return -1;}

     while( ( ( inb(UART_LSR + UART) ) & UART_LSR_DR ) == 0 ){
             schedule();
     }
     buf = inb(UART);
     return (char)buf;
}

在我的测试程序中我调用它

    rb = read(fd, buffer, sizeof(buffer));
    if ( rb < 0){
        perror("Error");
    }
    else {
        buffer[rb] = '\0';
    }

因此,从我在测试程序中调用它的那一刻起,除非 UART 得到一些字符,否则我无法退出。但我希望能够中断这个过程。我可以做一个普通的处理程序来处理 CTRL-C 吗?还是我必须为相同的效果做一些不同的事情?如果调用了处理程序,那么内核程序之后会去哪里?或者如果我在测试程序中有一个普通的处理程序,内核会发生什么?它会起作用吗?

此外,内核代码是一个程序,而测试程序完全是另一个程序。

4

2 回答 2

0

EDIT2: ctrl+c 发出一个可以处理的信号(SIGINT)sigaction()

------------IGNORE MODE ON(根据@undefined-behaviour)-------------

此代码处理 ctrl+c

编辑:这应该有'ctrl+c'字符但stackoverflow没有显示它(它的十进制/八进制/十六进制:0003)while ((a!='A')&&(a!='ctrl+c'));

#include <stdio.h>
#include <unistd.h> /*_getch*/
#include <termios.h>    /*_getch*/


char getch() {
    /*#include <unistd.h>   //_getch*/
    /*#include <termios.h>  //_getch*/
    char buf=0;
    struct termios old = {0};
    fflush(stdout);
    if(tcgetattr(0, &old) < 0)
        perror("tcsetattr()");
    old.c_lflag&=~ICANON;
    old.c_lflag &= ~ECHO;
    old.c_cc[VMIN]=1;
    old.c_cc[VTIME]=0;
    if(tcsetattr(0, TCSANOW, &old) < 0)
        perror("tcsetattr ICANON");
    if(read(0,&buf,1)<0)
        perror("read()");
    old.c_lflag=ICANON;
    old.c_lflag=ECHO;
    if(tcsetattr(0, TCSADRAIN, &old) < 0)
        perror ("tcsetattr ~ICANON");
    printf("%c\n",buf);
    return buf;
}

int main(int argc, char *argv[]){
    char a;
    do{
        a=getch();
        printf("%d-%c \n",a,a);
    }while ((a!='A')&&(a!='ctrl+c'));   /* ctrl+c ;  backspace ;� multi-char cte ; ç 135*/
    printf("\n");
    return 0;
}
于 2013-05-20T16:30:08.803 回答
0

我相信您可以做的是在您的应用程序级别编写一个信号处理程序,它可以捕获 SIGINT (ctrl+c) 或您选择的任何信号(前提是我们可以处理这些信号)

并从信号句柄调用 IOCTL 调用到内核中的驱动程序,这反过来应该重新安排内核读取可能是逻辑上的变化,如下所示

你需要在内核中实现一个 IOCTL 调用以及这个

 /** This NO_SIGNAL_FROM_USER is a GLOBAL variable at kernel 
             which should be set based on your IOCTL**/

 while( (( ( inb(UART_LSR + UART) ) & UART_LSR_DR ) == 0 ) && (NO_SIGNAL_FROM_USER)){
             schedule();
     }

并在您阅读时进行一些更改

for (i = 0; i != count && NO_SIGNAL_FROM_USER ; ++i) {
            buffer[i] = UART_read();
            if(buffer[i] == '\n')
                break;
        }
/*** RESET THE SIGNAL HERE AGAIN ***/

PS - 哎呀忘记了可能你需要在你的用户应用程序中的信号处理程序上做更多的处理,但这又取决于我猜。

于 2013-05-20T16:54:39.883 回答