linux系统调用及错误处理

原文地址http://daileinote.com/computer/linux_sys/02

系统调用是内核提供给外部程序的接口,进程可以通过系统调用来一自己的名义来执行某些动作。在深入了解系统调用之前,先关注以下几点。
1.系统调用处理器会从用户态切换到核心态以便能访问到内存核心空间。
2.系统调用的组成是固定的,每个系统调用都有一个唯一的数字来标识,而程序只是通过名称来调用。

从编程角度来讲,它跟c语言函数的调用很像,但是系统调用会经历的步骤往往更多。

 

系统调用内部细节已超出了本文的范围,普通的linux编程只需要记住以下几点
1.普通的一次系统调用开销是一次普通c库函数调用的20倍以上,所以用c普通函数解决的绝不用系统调用。
2.系统调用内核还需验证系统调用参数,用户空间内存和内核控件内存的复制
3.系统调用后我们都必须检查下返回值以及全局变量errno来确定系统调用是否报错了。
4.在linux上如果想检查一个程序执行了哪些系统调用,可用strace命令。

系统调用错误处理

系统调用的手册里都有记录调用可能的返回值,并指出哪些返回值表示错误。通常返回值是-1表示出错。
系统调用失败时会将全局整形变量errno设置为一个正值来标识具体错误。头文件<errno.h>提供了对errno的声明以及一些跟错误码有关的常量定义。
系统调用和库函数调用成功errno不会被重置为0,因此我们不能直接来判断errno来确定错误,有可能是之前的函数失败造成的。因此在检查错误时,必须先判断返回值,如果出错再根据errno来确定具体错误。
少数系统调用(如getpriority())在调用成功后也会返回-1,要判断此类系统调用是否发生错误,应提前将errno置为0,然后调用后再对errno进行判断。

void perror(const char *msg);
此函数会打印出字符串msg紧跟与当前errno值对应的错误描述。

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){
    int fd = open("aaa", O_WRONLY);
    if(fd == -1){
        perror("open");
    }
    
    return -1;
}
//open: No such file or directory

 

char *strerror(int errnum);
该函数会根据errnum错误号返回错误描述字符串,由于返回的字符串是静态分配的,这就意味着后续调用strerror()可能会覆盖之前的字符串,所以如果该错误描述后续还要用到,建议复制一个副本。

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

int main(){
    int fd = open("aaa", O_WRONLY);
    char *tmp = strerror(errno);
    printf("errno:%d, %s\n", errno,tmp);
    
    printf("errno:%d, %s\n", 3,strerror(3));
    printf("errno:%d, %s\n", 4,strerror(4));
}
/*
errno:2, No such file or directory
errno:3, No such process
errno:4, Interrupted system call
errno:1111, Unknown error 1111
*/

注意由于perror和strerror函数跟本地环境有关,所以如果你的linux是中文版的,则输出的字符串也会变成中文。

 

原文地址http://daileinote.com/computer/linux_sys/02

发布了44 篇原创文章 · 获赞 4 · 访问量 6万+
展开阅读全文

linux 用户态调用驱动中的函数返回-1

11-13

/*****************驱动代码***************/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irqreturn.h> #include <mach/hardware.h> #include <mach/sysheap.h> #include <asm/io.h> #include <linux/spinlock.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/irqreturn.h> #include <linux/slab.h> #include <asm/delay.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <mach/irqs.h> #include <mach/sysheap.h> #include <asm/timex.h> #include "pciedrv.h" #define GLOBAL_MAJOR 133 PCIE_DRV_CONTEXT pcieContext; S32 x4orx1; #define WRITE_DMA_AND_SEND 0x100 #define READ_FROM_BUFFER 0x200 #define BUSY 0x10 #define IDLE 0x11 #define EXIT 0x12 #define GLOBALMEM_MAJOR 133 #define TRANSMIT _IOC (_IOC_READ,IOCTL_MAGIC, 3, 4 ) #define RECEIVE _IOC (_IOC_WRITE,IOCTL_MAGIC,4, 4 ) ssize_t DriverRead (struct file* stFileName, const char __user* input, size_t size, loff_t* offset); ssize_t DriverWrite (struct file* stFileName, const char __user* input, size_t size, loff_t* offset); struct file_operations globalmem_fops = { .owner = THIS_MODULE, .read = DriverRead, .write = DriverWrite, }; static globalmem_major = GLOBALMEM_MAJOR; struct globalmem_dev { struct cdev cdev; unsigned char mem[0x10000]; }; struct globalmem_dev dev; ssize_t DriverRead (struct file* stFileName, const char __user* input, size_t size, loff_t* offset) { printk("%s\n",__FUNCTION__); return 0; } ssize_t DriverWrite(struct file* stFileName, const char __user* input, size_t size, loff_t* offset) { printk("%s\n",__FUNCTION__); return 0; } static int __init_func(void) { int retValue = 0; dev_t devno = MKDEV(globalmem_major, 0); if(globalmem_major) { retValue = register_chrdev_region(devno, 1, "pciedrv"); printk(KERN_ALERT "register charactor device region\n"); } else { retValue = alloc_chrdev_region(devno, 0, 1, "pciedrv"); globalmem_major = MAJOR(devno); printk(KERN_ALERT "alloc charactor device region\n"); } if(retValue <0) { printk("Failed to register or alloc major\n"); } devno = MKDEV(globalmem_major, 0); cdev_init(&dev.cdev, &globalmem_fops); dev.cdev.owner = THIS_MODULE; dev.cdev.ops = &globalmem_fops; retValue = cdev_add(&dev.cdev,devno,1); if(retValue) printk("cdev_add return %d\n",retValue); retValue = PCIeDrvInit(PCIE0_BASEADDR, x4orx1); if(retValue == 0) printk(KERN_ALERT "PCIeDrvInit Success!\n "); else printk(KERN_ALERT "PCIeDrvInit Failed!\n"); control_buffer.status = 0; control_buffer.command = 0; printk(":D\n"); return retValue; } static void __exit_func(void) { printk(KERN_ALERT "Here is entering the exit-point of the PCIE driver!!! \n"); cdev_del(&dev.cdev); unregister_chrdev_region(MKDEV(globalmem_major, 0), 1); PCIeDrvDeinit(); } module_init(__init_func); module_exit(__exit_func); MODULE_AUTHOR("ZCTT"); MODULE_DESCRIPTION("Driver of PCIEx4"); MODULE_ALIAS("ICC Driver"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(__init_func); EXPORT_SYMBOL(__exit_func); /**************************调用函数代码***********************************/ #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> #include <string.h> #include <unistd.h> #define DEVICE_FILENAME "/bin/pciedrv.ko" #define DEVICE_TYPE (0xA4<<24) #define DEVICE_SERIAL (0x33<<16) #define DEVICE_DERICTION IOC_NON #define READ_PHY_ADDRESS 0x100 #define WRITE_PHY_ADDRESS 0x101 #define GLOBAL_MAJOR 133 #define IOCTL_MAGIC 't' typedef struct { unsigned long size; unsigned int offset; unsigned char buff [128]; }__attribute__((packed)) ioctl_read_info_t; typedef struct { unsigned long size; unsigned int offset; unsigned char buff [128]; }__attribute__((packed)) ioctl_write_info_t; ioctl_read_info_t ioctl_read_info ; ioctl_write_info_t ioctl_write_info ; int main() { char* str = "Hello Guys This is the Message!\n"; int retValue ; int dev = 0; memset (ioctl_write_info.buff, 0, 128); ioctl_write_info.size = strlen(str)+1; ioctl_write_info.offset = 0; memcpy (ioctl_write_info.buff, str, ioctl_write_info.size); /**********************************************************/ dev = open(DEVICE_FILENAME, O_RDWR); printf("dev = %d\n",dev); printf(":--\n"); while(1) { int retValue = read(dev, str, strlen(str)); printf ("retValue = %d\n",retValue); sleep(2); write(dev, str, strlen(str)); printf ("retValue = %d\n",retValue); } printf("Finished system calling! \n"); /运行结果/ 驱动部分的dmesg,事实上只打印出了init部分的内容 register charactor device region :D root@OpenWrt:~# a.out dev = 3 :-- retValue = -1 retValue = -1 retValue = -1 retValue = -1 retValue = -1 retValue = -1 retValue = -1 ^C 运行完a.out之后 demesg发现没有任何新增内容。 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览