Linux基础IO

1、文件相关系统调用接口open/read/write/close的实现,fd与FILE结构体 的纵向对比

1.1、open函数介绍:用于打开一个指定文件

1.1.2、函数原型:int open(const char *pathname, int flags);       

1.1.3、参数及返回值说明:

pathname    文件名  
 *          flags       选项标志   O_RDWR | O_CREAT | O_TRUNC | O_APPEND
 *              只能选其一/也必选其一
 *              O_RDONLY    只读
 *              O_WRONLY    只写
 *              O_RDWR      读写
 *              可选:
 *              O_CREAT     文件不存在则创建,存在则打开
 *              O_TRUNC     打开文件的时候清空原有内容
 *              O_APPEND    写数据的时候总是追加在文件末尾
 *          mode        文件权限
 *              S_IWUSR | S_IXUSR|S_IRWXG.........
 *              0664
 *          返回值:文件描述符(正整数)    失败:-1   

1.2、read函数介绍:读取指定文件

1.2.1、函数原型:ssize_t read(int fd, void *buf, size_t count);

1.2.2‘参数及返回值说明:

  * ssize_t read(int fd, void *buf, size_t count);
 * fd    文件描述符
 * buf    定义的缓冲区
 * count  要读取的数据字节数
 *返回值:成功返回读取到字节数   失败:-1

1.3、write函数介绍 :往指定文件中写入数据
 

1.3.1、函数原型:  ssize_t write(int fd, const void *buf, size_t count);     
1.3.2、参数及返回值说明: 

* fd    文件描述符
 * buf    写入的内容
 * count   写入的字节数
 *返回值:成功时返回写入的字节数  失败:-1

1.4、close函数介绍:关闭指定文件

1.4.1、函数原型:int close(int fd);   

1.4.2、参数及返回值说明:
 * fd    指定文件描述符          
 * 返回值:成功:0    失败:-1

1.5、实现代码:

/**********************************************************
 * Author        : WangWei
 * Email         : 872408568@qq.com
 * Last modified : 2019-04-28 16:50:59
 * Filename      : open.c
 * Description   :文件相关系统调用接口open/read/write/close的实现
 * int open(const char *pathname, int flags);   打开指定文件
 * pathname    文件名  
 * flags       选项标志   O_RDWR | O_CREAT | O_TRUNC | O_APPEND
 *                只能选其一/也必选其一
 *                O_RDONLY    只读
 *                O_WRONLY    只写
 *                O_RDWR      读写
 *                可选:
 *                O_CREAT     文件不存在则创建,存在则打开
 *                O_TRUNC     打开文件的时候清空原有内容
 *                O_APPEND    写数据的时候总是追加在文件末尾
 * mode        文件权限
 *                S_IWUSR | S_IXUSR|S_IRWXG.........
 *                0664
 * 返回值:文件描述符(正整数)    失败:-1   
 *
 * ssize_t read(int fd, void *buf, size_t count);          读取指定文件
 * fd    文件描述符
 * buf    定义的缓冲区
 * count  要读取的数据字节数
 *返回值:成功返回读取到字节数   失败:-1

 *  ssize_t write(int fd, const void *buf, size_t count);     往指定文件中写入数据
 * fd    文件描述符
 * buf    写入的内容
 * count   写入的字节数
 *返回值:成功时返回写入的字节数  失败:-1
 * int close(int fd);    关闭指定文件
 * fd    指定文件描述符          
 * 返回值:成功:0    失败:-1
 * *******************************************************/

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

int main()
{
  
    char* file = "1.txt";
    //   int open(const char *pathname, int flags, mode_t mode)
    umask(0);  // 设置默认权限掩码
    int fd = open(file , O_RDWR | O_CREAT , 0664);
    if(fd < 0) {
        perror("open error");
        return -1;
    }
    
    // ssize_t write(int fd, const void *buf, size_t count);
    char buf[1024] = "hello bit !";
    int ret = write(fd, buf , 1024);
    if(ret < 0) {
        perror("write error");
        return -1;
    }
    // off_t lseek(int fd, off_t offset, int whence);   重新定位读/写文件偏移量
    //  fd: 打开文件返回的操作句柄--文件描述符
    //  offset: 偏移量
    //  whence:偏移起始位置
    //      SEEK_SET
    //      SEEK_CUR
    //      SEEK_END
    //  返回值:偏移的位置到文件起始位置的偏移量
    lseek(fd, 0, SEEK_SET);


    memset(buf,0x00,1024);
    // ssize_t read(int fd, void *buf, size_t count);
   ret =  read(fd, buf, 1023);
   if(ret < 0) {
       perror("read error");
       return -1;
   }
   else if(ret == 0) {
       printf("have no date \n");
       return -1;
   }

   printf("buf:%d %s \n",ret,buf);
   close(fd);

    return 0;
}

1.6、fd与FILE结构体 的纵向对比

(1)fd属于系统库 , FILE属于c标准库;

(2)fd是一个整数,FILE是一个结构体.

 


2、使minishell支持输入/输出/追加重定向 

/**********************************************************
 * Author        : WangWei
 * Email         : 872408568@qq.com
 * Last modified : 2019-04-28 21:00:40
 * Filename      : shell.c
 * Description   : 使minishell支持输入/输出/追加重定向 
 * minishell实现步骤:
 *      1、获取标准输入
 *      2、解析得到的字符串
 *      3、创建子进程,进行程序替换
 *      4、父进程进行进程等待
 * *******************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
int main()
{
    char buf[1024] = {0};
    while(1) {
        printf("[user@locahost]$");
        fflush(stdout);

        memset(buf,0x00,1024);

        if(scanf("%[^\n]%*c",buf) != 1) { 
        // ^表示"非",[^\n]表示读入换行字符就结束读入。这个是scanf的正则用法,我们都知道scanf不能接收空格符,但是使用%[^\n]就可以了。
       // *表示该输入项读入后不赋予任何变量,即scanf("%*[^\n]%*c")表示跳过一行字符串。
            getchar();
            continue;
        }

        // 创建子进程
        int pid = fork();
        if(pid < 0) {
            perror("fork error");
            return -1;
        }
        else if(pid == 0){
            char *str = buf;
            int count = 0;  // 重定向符号个数
            char *file = NULL;
            int fd = 0;

            // 找重定向个数
            while(*str != '\0') {

                if(*str == '>') {
                    count++;
                    *str = '\0';
                    
                    if(*(str + 1) == '>') {
                        count++;

                    }
                    str += count;

                    while(*str != '\0' && !isspace(*str)) {
                        *str++ = '\0';
                    }

                    file = str;

                    // 走完文件
                    while(*str != '\0' && !isspace(*str)) {
                        str++;
                    }
                    *str = '\0';
                    continue;
            }
                str++;
        }
            if(count == 1) {
                fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0664);
             
                // int dup2(int fd1, int fd2)   
                // 用dup2则可以用fd2参数指定新的描述符数值。
                // 如果fd2已经打开,则先关闭。若fd1=fd2,则dup2返回fd2,而不关闭它。
                dup2(fd,1);
            }
            else if(count == 2) {
                  fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0664);
                  dup2(fd,1);
            }

            // 解析外部命令
            char *ptr = buf;
            char *argv[64];
            int argc = 0;
            while(*ptr != '\0') {
                if(!isspace(*ptr)) {
                    argv[argc++] = ptr;
                    while(*ptr != '\0' && !isspace(*ptr)) {
                        ptr++;
                    }
                }
                *ptr = '\0';
                ptr++;
            }
            argv[argc] = NULL;

            //子进程进行程序替换
            //  int execvp(const char *file ,char * const argv []);
            //  execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,
            //  找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
            execvp(argv[0], argv);
            exit(0);
    }
        waitpid(pid, NULL, 0);
    }
    printf("Hello world\n");
    return 0;
}

3、编写简单的add/sub/mul/div函数,并打包成动/静态库,并分别使用。 

静态库:   

生成静态库:
① gcc -c  a.c -o a.o
② ar -rc libmytest.a a.o b.o
③ gcc main.c libmytest.a   将所有目标代码链接起来生成静态库    -c 创建   -r 模块替换 
//gcc main.c -lmytest
(标准版测试运行:gcc main.c  -L . -lmytest)

动态库 (共享库):
生成动态库:
gcc  -FPIC -shared -o libmytestso a.c
(其中 -FPIC 产生未知无关代码)

 

add.c

/**********************************************************
 * Author        : WangWei
 * Email         : 872408568@qq.com
 * Last modified : 2019-04-29 20:56:49
 * Filename      : add.c
 * Description   : 
 * *******************************************************/

#include "add.h"

int add(int a, int b) {
    return a + b;

}

add.h

/**********************************************************
 * Author        : WangWei
 * Email         : 872408568@qq.com
 * Last modified : 2019-04-29 20:56:49
 * Filename      : add.h
 * Description   : 
 * *******************************************************/


#ifndef _ADD_H

#define _ADD_H
int add(int a, int b);

#endif

 

sub.h

/**********************************************************
 * Author        : WangWei
 * Email         : 872408568@qq.com
 * Last modified : 2019-04-29 21:04:10
 * Filename      : sub.c
 * Description   : 
 * *******************************************************/
#include "sub.h"

int sub(int a, int b) {
    return a - b ;

}

sub.h

#ifndef _SUB_H
#define _SUB_H
int sub(int a, int b);

#endif

mul.c

#include "mul.h"

int mul(int a, int b) {
    return a * b;

}

mul.h

#ifndef _MUL_H

#define _MUL_H
int mul(int a, int b);

#endif

div.c

/**********************************************************
 * Author        : WangWei
 * Email         : 872408568@qq.com
 * Last modified : 2019-04-29 21:08:23
 * Filename      : div.c
 * Description   : 
 * *******************************************************/
#include "div.h"

int div(int a, int b) {
    return a / b;
}

div.h

#ifndef _DIV_H

#define _DIV_H
int div(int a, int b);

#endif

main.c

/**********************************************************
 * Author        : WangWei
 * Email         : 872408568@qq.com
 * Last modified : 2019-04-29 21:10:19
 * Filename      : main.c
 * Description   : 
 * *******************************************************/

#include <stdio.h>

#include "add.h"
#include "sub.h"
#include "mul.h"
#include "div.h"

int main()
{
    int a;
    int b;

    printf("请输入两个整数:");
    scanf("%d %d", &a, &b);

    printf("[add]:%d \n",add(a, b));
    printf("[sub]:%d \n",sub(a, b));
    printf("[mul]:%d \n",mul(a, b));
    printf("[div]:%d \n",div(a, b));

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值