protobuf无法使用open函数打开文件

说了一大堆就是说open函数在Windows下的在io.h头文件下,Linux下的在fcntl.h头文件下。同时若直接使用这个,则vs编译会提示error C4996: 'open': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _open. See online help for details.
这是因为在vs下open函数已经被废弃,vs建议使用_open但使用_open又会出现error C4996: '_open': This function or variable may be unsafe. Consider using _sopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
在工程设置里预编译头加上_CRT_SECURE_NO_WARNINGS即可不关心原因看到这里就结束了。

今天在使用protobuf做简单的参数存取时发现,Windows下无法使用open函数获取文件描述符

open 函数用于打开和创建文件。以下是 open 函数的简单描述

#include <fcntl.h>
int open(const char *pathname, int oflag, ... );

于是查了下。

在Linux下open函数是在fcntl.h头文件中的(该头文件中包含了许多文件打开的模式定义和create、fcntl、open等函数),windows也有该头文件(但仅包含了一些文件打开模式的定义)。

Linux下fcntl.h内容:http://pubs.opengroup.org/onlinepubs/009695399/basedefs/fcntl.h.html

因此判定fcntl.h并不是标准库函数。查了下,果然如此(不得不说基础知识掌握不牢固啊)。

该头文件不属于标准库函数,且Windows下的fcntl.h头文件下没有该函数并不代表这个功能不能用,或者Windows下不能使用这个功能。毕竟protobuf就提供了这个接口。

查了写资料,有人说FILE结构体中包含了文件描述符这个字段,其形式如下(其中_file就是Linux下的文件描述符fd):

struct _iobuf {  
      char *_ptr; 
      int _cnt; 
      char *_base; 
      int _flag; 
      int _file;//文件描述符
      int _charbuf; 
      int _bufsiz;
      char *_tmpfname;
  };  
typedef struct _iobuf FILE;  

但是我在VS2015下查找了下,发现其实现形式并非如此,而是这样:


//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// Stream I/O Declarations Required by this Header
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#ifndef _FILE_DEFINED
    #define _FILE_DEFINED
    typedef struct _iobuf
    {
        void* _Placeholder;
    } FILE;
#endif

因此认为应该是编译环境升级导致数据结构与原先发生了一些改变,无法使用(瞎猜的)。

后查阅资料发现vs下可用io.h头文件中的open函数实现获取文件描述符的功能

C标准库

C标准库,顾名思义既然是标准,就是由标准组织制定的。

是由“美国国家标准协会(American National Standards Institute,ANSI)”为了规范C语言库而制定的标准。在最初,各个大学各个公司使用的C语言库都不尽相同,造成相互移植非常困难,在这个背景下,制定了这个标准。

下面是标准库函数的头文件:

标准头名 功能 描述
<assert.h> 诊断 仅包含assert宏。可以在程序中使用该宏来诊断程序状态(例如某个变量是否为0等),若检查失败,程序终止。
<ctype.h> 字符处理 包含判断字符类型及大小写转换的函数。
<errno.h> 错误监测 提供了errno。可以在调用特定库函数后检测errno的值以判断调用过程中是否有错误发生。
<float.h> 浮点数特性 提供了描述浮点数特性的宏。
<limits.h> 整型特性 提供了描述整数类型和字符类型特性的宏。
<locale.h> 本地化 提供了一些支持程序国际化的函数。
<math.h> 数学计算 提供了大量用以数学计算的函数。
<setjmp.h> 非本地跳转 提供了用于绕过正常的函数返回机制,从一个函数跳转到另一个正在活动的函数的setjmplongjmp函数。
<signal.h> 信号处理 提供了包括中断和运行时错误在内的异常情况处理函数。
<stdarg.h> 不定参数 提供了支持函数处理不变个数的参数的工具。
<stddef.h> 常用定义 提供了常用的类型和宏。
<stdio.h> 输入输出 提供了大量输入输出函数。
<stdlib.h> 常用实用函数 提供了大量实用的函数。
<string.h> 字符串处理 提供了大量字符串处理函数。
<time.h> 日期和时间 提供了获取、操纵和处理日期的函数。

C运行库

C运行库,是和平台相关的,即和操作系统相关的。

它由不同操作系统不同开发平台提供不同的C运行库。但是C运行库的部分实现是基于C标准库的,即C运行库是各个操作系统各个开发工具根据自身平台开发的库,某种程度上,可以说C运行库是C标准库的一个扩展库,只是加了很多C标准库所没有的与平台相关的或者不相关的库接口函数。举例子如:c标准库的strcpy函数负责字符串的拷贝,但是由于缺少对目地字符串缓冲区大小的控制,极有可能导致缓冲区溢出(大量的缓冲区溢出攻击都是由于这种漏洞而产生的);相反,Windows提供了能够实现同样功能的安全的字符串拷贝函数,减少了缓冲区攻击的可能,strcpy_s。这些函数是以c运行库的方式提供的,当然,不同的操作系统,c运行时库可能不同,但是对c标准库的支持是完全一致的,也就是说,在不同的操作系统上,使用同一个c标准库的函数必然产生一致的结果。

一个C运行库大致包含了如下功能:
* 启动与退出:包括入口函数及入口函数所依赖的其他函数等。
* 标准函数:由C语言标准规定的C语言标准库所拥有的函数实现。(C标准库)
* I/O:I/O功能的封装和实现,参见上一节中I/O初始化部分。
* 堆:堆的封装和实现,参见上一节中堆初始化部分。
* 语言实现:语言中一些特殊功能的实现。
* 调试:实现调试功能的代码。

总结一下,C标准库就是任何平台都可以使用的基本C语言库。而CRT除了将C标准库加入所属范围外,还扩展了与平台相关的接口库,这些接口实现根据不同平台调用不同平台的操作系统API。

如下图所示,采用C标准库编写的程序可以应用到windows平台,也可以应用到linux平台;而用CRT另外与平台相关的库函数编写的应用程序不能跨平台运行。

protobuf无法使用open函数打开文件

参考资料:

http://blog.csdn.net/a379039233/article/details/51062705 FILE以前的数据结构形式

http://blog.csdn.net/babygjx/article/details/5740038 io.h头文件下的一些函数

http://blog.csdn.net/lemonrabbit1987/article/details/47970861 C语言标准库概述

https://www.cnblogs.com/renyuan/p/5031100.html 详细分析了C语言标准库和C运行库的区别