系统调用与标准函数库(上)

来源:互联网 发布:卡盟域名中毒怎么办? 编辑:程序博客网 时间:2024/05/03 16:49

        所谓系统调用其实是操作系统提供给用户程序的一组“特殊”函数接口,可以直接这么去理解,操作系统是一个很大的“函数库”,它给程序员提供了很多可以调用的函数。

       系统调用按照功能逻辑大致可分为:进程控制、进程间通信、文件系统控制、系统控制、内存管理、网络管理、socket控制、用户管理。在Linux的不同版本中,提供了两三百个系统调用,用户程序可以通过这组接口获得操作系统(内核)提供的服务。例如,用户可以通过文件系统相关的系统调用,请求系统打开文件、关闭文件或读写文件。下图是类UNIX系统的软件层次图:

                   

        应用程序可以通过系统调用接口陷入内核,内核再通过相应驱动程序去控制底层的硬件。当然应用程序进行系统调用有多种方式,如下图所示:(1)应用程序直接调用系统调用,(2)通过shell命令,(3)通过标准库函数,其实这些库函数也都是系统调用的封装出来的,比如fread()函数就是封装系统调用read()而来的,当然并不是所有的系统调用都被封装成了库函数。

                                        


        1. 系统调用I/O函数

        系统调用中操作I/O的函数,都是针对文件描述符的,通过文件描述符可以直接对相应的文件进行操作,如:open、close、write 、read、ioctl。就像我C语言博文中关于文件操作那篇一样,无非那些是标准库下的函数,是对系统调用中操作I/O的函数封装后的库函数,原理都是一样,C标准库中有关文件的FILE结构体中包含了文件描述符和一些关于流缓冲区的信息。
        这里简单解释下文件描述符的概念,文件描述符本质就是一个非负整数,是你在用open系统调用打开现存文件或新建文件时,系统(内核)返回给你的,它用来
指定已打开的文件

        #define STDIN_FILENO     0  //标准输入的文件描述符

        #define STDOUT_FILENO 1 //标准输出的文件描述符

        #define STDERR_FILENO 2 //标准错误的文件描述符
        上面这三个是特殊的文件描述符,在程序运行起来后是默认打开的。

        1.1 open函数:打开一个文件

        当文件存在时使用:int open(const char *pathname, int flags);
        当文件不存在时使用:int open(const char *pathname, int flags, mode_t mode);
        参数:pathname:文件的路径及文件名。
                   flags:open函数的行为标志。
                   mode:文件权限(可读、可写、可执行)的设置。
        返回值:成功返回打开的文件描述符,失败返回-1,可以利用perror去查看原因(下同)。

        1.2 close函数:关闭一个文件
        int close(int fd);
        参数:fd是调用open打开文件返回的文件描述符。
        返回值:成功返回0,失败返回-1。

        1.3 read/write函数:把指定数目的数据读到内存或写到文件

        ssize_t read/write(int fd, const void *addr, size_t count);
        参数:fd:文件描述符。
        addr:内存首地址/数据首地址。
        count:写入数据的字节个数。
        返回值:成功返回实际读出/写入数据的字节个数,失败返回-1。

        1.4 remove函数:删除文件
        int remove(const char *pathname); 
        参数:pathname :文件的路名+文件名。
        返回值:成功返回0,失败返回-1。

        1.5 例系统调用实现cp命令

        #include <stdio.h>
        #include <stdlib.h>
        #include <malloc.h>
        #include <unistd.h>//write read
        #include <sys/types.h> //open
        #include <sys/stat.h>
        #include <fcntl.h>
        #define  BUF_SIZE 1024
        int main(int argc,char *argv[])
        {
                int fd_src,fd_dest;
                char buf[BUF_SIZE]="";
                int ret = 0;
                if(argc != 3)
                {
                        printf("miss parameters,please check your input!\n");
                        exit(-1);
                }
                else
                {
                        fd_src = open(argv[1],O_RDONLY);
                        fd_dest = open(argv[2],O_WRONLY|O_CREAT,0666);
                        if((fd_src == -1) || (fd_dest == -1))
                        {
                                perror("open file");
                                exit(-1);
                        }
                        //拷贝到目的文件
                        ret = read(fd_src,buf,BUF_SIZE);
                        while(ret > 0)
                        {
                                ret  = write(fd_dest,buf,ret);
                                if(ret == -1)
                               {
                                        perror("write file");
                                        exit(1);
                                }
                                ret = read(fd_src,buf,BUF_SIZE);
                        }
                        close(fd_src);
                        close(fd_dest);
                }
               return 0;
        }

1 0
原创粉丝点击