对比windows和linux的对父进程的文件描述符继承的设置

来源:互联网 发布:3cdaemon 端口 编辑:程序博客网 时间:2024/05/17 22:52

需要实现一个fopen中的子进程是否继承父进程的文件句柄的功能。

由于在多平台上,所以需要考虑windows和Linux及类Unix系统。

Linux实现的阻碍:

Linux中是默认子进程能够继承fd的。

1.由于需要在fopen函数中实现,但是看了下关于O_CLOEXEC属性(since Linux 2.6.23)是在open函数中的。

其含义就是在获取新的文件描述符时,使能close-on-exec flag,即使得在调用exec函数集时主动预先关闭父进程的文件描述符。

这在open中是一个Flag,也就是说是一个int型值。

2.正由于open中是一个int型值,而其他的文件属性相关的大部分在fopen都是rw等以char*形式提供的mode。所以出现了不好统一的的情况。

汇集一点:open中提供了对应的int型的flag,但是我们要打开的是文件需要调用fopen,fopen又没有提供int型的设置参数,只有字符串类型的mode作为设置参数。

解决办法:

还是查资料,发现了在glibc中,fopen已经提供了类似的参数在mode中,以字符'e'表示O_CLOEXECflag。但是这里有一个限制,就是必须要是glibc 2.7版本以后才会有这种解析。如果是之前的版本,就只好先用open接口加上O_CLOEXEC的flag做为参数获取到fd,然后再利用fdopen,来进行mode的设置。


windows的实现阻碍:

windows中是默认子进程能够不能继承fd的,因为要提前设置好条件。

其实关键在于,这个实现的有没有意义。因为下面的资料上也有提及,如果要继承父进程的句柄,则需要有两步

1.在创建获取句柄(类似于文件描述符)的时候,就要明确在属性中设置是可以用于子进程继承的。

2.在创建子子进程时,是否允许继承的参数就要设置成true,否则仍然不能继承。


摘自:http://man7.org/linux/man-pages/man3/fopen.3.htm

NAME         top

       fopen, fdopen, freopen - stream open functions

SYNOPSIS         top

       #include <stdio.h>       FILE *fopen(const char *path, const char *mode);       FILE *fdopen(int fd, const char *mode);       FILE *freopen(const char *path, const char *mode, FILE *stream);   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):       fdopen(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

DESCRIPTION         top

       The fopen() function opens the file whose name is the string pointed       to by path and associates a stream with it.       The argument mode points to a string beginning with one of the       following sequences (possibly followed by additional characters, as       described below):       r      Open text file for reading.  The stream is positioned at the              beginning of the file.       r+     Open for reading and writing.  The stream is positioned at the              beginning of the file.       w      Truncate file to zero length or create text file for writing.              The stream is positioned at the beginning of the file.       w+     Open for reading and writing.  The file is created if it does              not exist, otherwise it is truncated.  The stream is              positioned at the beginning of the file.       a      Open for appending (writing at end of file).  The file is              created if it does not exist.  The stream is positioned at the              end of the file.       a+     Open for reading and appending (writing at end of file).  The              file is created if it does not exist.  The initial file              position for reading is at the beginning of the file, but              output is always appended to the end of the file.       The mode string can also include the letter 'b' either as a last       character or as a character between the characters in any of the two-       character strings described above.  This is strictly for       compatibility with C89 and has no effect; the 'b' is ignored on all       POSIX conforming systems, including Linux.  (Other systems may treat       text files and binary files differently, and adding the 'b' may be a       good idea if you do I/O to a binary file and expect that your program       may be ported to non-UNIX environments.)       See NOTES below for details of glibc extensions for mode.       Any created files will have mode S_IRUSR | S_IWUSR | S_IRGRP |       S_IWGRP | S_IROTH | S_IWOTH (0666), as modified by the process's       umask value (see umask(2)).       Reads and writes may be intermixed on read/write streams in any       order.  Note that ANSI C requires that a file positioning function       intervene between output and input, unless an input operation       encounters end-of-file.  (If this condition is not met, then a read       is allowed to return the result of writes other than the most       recent.)  Therefore it is good practice (and indeed sometimes       necessary under Linux) to put an fseek(3) or fgetpos(3) operation       between write and read operations on such a stream.  This operation       may be an apparent no-op (as in fseek(..., 0L, SEEK_CUR) called for       its synchronizing side effect).       Opening a file in append mode (a as the first character of mode)       causes all subsequent write operations to this stream to occur at       end-of-file, as if preceded the call:           fseek(stream, 0, SEEK_END);       The fdopen() function associates a stream with the existing file       descriptor, fd.  The mode of the stream (one of the values "r", "r+",       "w", "w+", "a", "a+") must be compatible with the mode of the file       descriptor.  The file position indicator of the new stream is set to       that belonging to fd, and the error and end-of-file indicators are       cleared.  Modes "w" or "w+" do not cause truncation of the file.  The       file descriptor is not dup'ed, and will be closed when the stream       created by fdopen() is closed.  The result of applying fdopen() to a       shared memory object is undefined.       The freopen() function opens the file whose name is the string       pointed to by path and associates the stream pointed to by stream       with it.  The original stream (if it exists) is closed.  The mode       argument is used just as in the fopen() function.  The primary use of       the freopen() function is to change the file associated with a       standard text stream (stderr, stdin, or stdout).

RETURN VALUE         top

       Upon successful completion fopen(), fdopen() and freopen() return a       FILE pointer.  Otherwise, NULL is returned and errno is set to       indicate the error.

NOTES         top

   Glibc notes       The GNU C library allows the following extensions for the string       specified in mode:       c (since glibc 2.3.3)              Do not make the open operation, or subsequent read and write              operations, thread cancellation points.  This flag is ignored              for fdopen().       e (since glibc 2.7)              Open the file with the O_CLOEXEC flag.  See open(2) for more              information.  This flag is ignored for fdopen().       m (since glibc 2.3)              Attempt to access the file using mmap(2), rather than I/O              system calls (read(2), write(2)).  Currently, use of mmap(2)              is attempted only for a file opened for reading.       x      Open the file exclusively (like the O_EXCL flag of open(2)).              If the file already exists, fopen() fails, and sets errno to              EEXIST.  This flag is ignored for fdopen().       In addition to the above characters, fopen() and freopen() support       the following syntax in mode:           ,ccs=string       The given string is taken as the name of a coded character set and       the stream is marked as wide-oriented.  Thereafter, internal       conversion functions convert I/O to and from the character set       string.  If the ,ccs=string syntax is not specified, then the wide-       orientation of the stream is determined by the first file operation.       If that operation is a wide-character operation, the stream is marked       wide-oriented, and functions to convert to the coded character set       are loaded.

BUGS         top




摘自:https://msdn.microsoft.com/en-us/library/windows/desktop/ms683463(v=vs.85).aspx 

Inheritance

A child process can inherit several properties and resources from its parent process. You can also prevent a child process from inheriting properties from its parent process. The following can be inherited:

  • Open handles returned by the CreateFile function. This includes handles to files, console input buffers, console screen buffers, named pipes, serial communication devices, and mailslots.
  • Open handles to process, thread, mutex, event, semaphore, named-pipe, anonymous-pipe, and file-mapping objects. These are returned by the CreateProcessCreateThreadCreateMutexCreateEventCreateSemaphoreCreateNamedPipe,CreatePipe, and CreateFileMapping functions, respectively.
  • Environment variables.
  • The current directory.
  • The console, unless the process is detached or a new console is created. A child console process can also inherits the parent's standard handles, as well as access to the input buffer and the active screen buffer.
  • The error mode, as set by the SetErrorMode function.
  • The process affinity mask.
  • The association with a job.

The child process does not inherit the following:

  • Priority class.
  • Handles returned by LocalAllocGlobalAllocHeapCreate, and HeapAlloc.
  • Pseudo handles, as in the handles returned by the GetCurrentProcess or GetCurrentThread function. These handles are valid only for the calling process.
  • DLL module handles returned by the LoadLibrary function.
  • GDI or USER handles, such as HBITMAP or HMENU.

Inheriting Handles

A child process can inherit some of its parent's handles, but not inherit others. To cause a handle to be inherited, you must do two things:

  • Specify that the handle is to be inherited when you create, open, or duplicate the handle. Creation functions typically use thebInheritHandle member of a SECURITY_ATTRIBUTES structure for this purpose. DuplicateHandle uses the bInheritHandlesparameter.
  • Specify that inheritable handles are to be inherited by setting the bInheritHandles parameter to TRUE when calling theCreateProcess function. Additionally, to inherit the standard input, standard output, and standard error handles, the dwFlagsmember of the STARTUPINFO structure must include STARTF_USESTDHANDLES.

An inherited handle refers to the same object in the child process as it does in the parent process. It also has the same value and access privileges. Therefore, when one process changes the state of the object, the change affects both processes. To use a handle, the child process must retrieve the handle value and "know" the object to which it refers. Usually, the parent process communicates this information to the child process through its command line, environment block, or some form of interprocess communication.

The DuplicateHandle function is useful if a process has an inheritable open handle that you do not want to be inherited by the child process. In this case, use DuplicateHandle to open a duplicate of the handle that cannot be inherited, then use theCloseHandle function to close the inheritable handle. You can also use the DuplicateHandle function to open an inheritable duplicate of a handle that cannot be inherited.

Inheriting Environment Variables

A child process inherits the environment variables of its parent process by default. However, CreateProcess enables the parent process to specify a different block of environment variables. For more information, see Environment Variables.

Inheriting the Current Directory

The GetCurrentDirectory function retrieves the current directory of the calling process. A child process inherits the current directory of its parent process by default. However, CreateProcess enables the parent process to specify a different current directory for the child process. To change the current directory of the calling process, use the SetCurrentDirectory function.


0 0
原创粉丝点击