Same file descriptor after fork() - fork

I'm trying to understand what means duplicating a file descriptor after calling fork() and its possible effects on contention.
In "The Linux Programming Interface" 24.2.1 (p517):
When a fork() is performed, the child receives duplicates of all of
the parent's file descriptors. These duplicates are made in the manner
of dup(), which means that corresponding descriptors in the parent and
the child refer to the same open file description.
When I run this same code:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void) {
char* fl = "/tmp/test_fd";
int fd;
fd = open(fl, O_CREAT|O_TRUNC|O_WRONLY, 0666);
if(!fork()) {
printf("cfd=%d\n", fd);
_exit(0);
} else {
int status;
printf("ffd=%d\n", fd);
wait(&status);
close(fd);
unlink(fl);
}
}
I get the same file descriptor (number?) for both processes: ffd=3 and cfd=3. But when run this code using dup():
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(void) {
char* fl = "/tmp/test_fd";
int cfd, ffd;
ffd = open(fl, O_CREAT|O_TRUNC|O_WRONLY, 0666);
cfd = dup(ffd);
printf("ffd=%d\n", ffd);
printf("cfd=%d\n", cfd);
close(ffd);
unlink(fl);
}
I get different file descriptors: ffd=3 and cfd=4.
Then, I have the following questions:
What means fork() creates a copy of the parent's file descriptors?
Is there contention when two processes (father and child) perform an operation like fstat() concurrently on the same file descriptor?
And what about two processes performing fstat() concurrently with two different file descriptors pointing to the same file?

When you see the phrase "duplicate a file descriptor", you need to understand it as "create a new file descriptor which points to the same thing the other one is pointing to".
So when you duplicate fd 3, you get fd 4. The aren't the same number, but they identify the same object.
In the case of fork, you must remember that the meaning of a file descriptor is contained within a process. Lots of processes have a valid fd 3, but they're not all referring to the same object. With fork, you have a duplicate of fd 3 that is also fd 3, but in a different process so those 3's aren't inherently identical; they're identical because fork made a copy.
You can close the fd and open a different file in the child process, and you'll still have two processes in which fd 3 is valid, but they aren't copies of the same thing anymore. Or you could have the child dup the fd 3 to get fd 4, then close fd 3, and then you'd have fd 3 in the parent and fd 4 in the child referring to the same object.
The same number in a different process doesn't mean anything.
Also note that the object referred to by a file descriptor isn't a file. There's something in between a file descriptor and a file, and it's called an open file description. Both fork and dup cause an open open file description to be shared. The main consequence of the sharing is that when the current file position (set by lseek or advanced by read and write) changes, all of the related file descriptors are affected, and when flags (like O_NONBLOCK) are changed, all the related file descriptors are affected.
In contrast if you open the same file twice, you get two file descriptors that refer to the same file, but through different open file descriptions, so they have independent flags and seek position.
fstat being a readonly operation, I don't see what kind of "contention" you're imagining for it.

Related

Specification of file descriptors

I am trying to understand flags and modes of file descriptors.
The man page for
fcntl - manipulate file descriptor
int fcntl(int fd, int cmd);
states:
File descriptor flags
The following commands manipulate the flags associated with a file
descriptor. Currently, only one such flag is defined: FD_CLOEXEC,...
File status flags
Each open file description has certain associated status flags,
initialized by open(2)...
The file status flags and their semantics are described in open(2).
Given that fcntl refers entirely to file descriptors (no dealing with streams), I guess the second title should be "File descriptor status flags".
So now we have for a FD "flags" and "status flags".
This man page also mentions that when cmd=F_GETFL, the return value of fcntl is "the file access mode and the file status flags".
So now we have also a file access mode.
Now in the man page for open
there are flags and modes, as if they were two different items.
There is even a prototype that makes explicit the difference
int open(const char *pathname, int flags, mode_t mode);
So now we have, for each file descriptor, "flags", "status flags", "file access modes", and "modes" (I would identify the latter two as the same).
To begin with,
1. I don't know the difference between these three categories.
Traversing both quoted man pages, I collected a list of "entities" (below, in order of appearance, some are repeated).
2. I don't know which category each belongs to.
FD_CLOEXEC, O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, O_NONBLOCK, O_DSYNC, O_SYNC, O_CLOEXEC
O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_TMPFILE, O_TRUNC, O_LARGEFILE, O_NDELAY, O_PATH
I couldn't find a simple list telling "X, Y, Z are flags, W, V are modes, etc."
Perhaps they are terms that are used interchangeably, or the mode is a subset of the flags, or...
Related:
Difference between "file pointer", "stream", "file descriptor" and ... "file"? (answers there may be a guide in the present OP, even if not the same).
How to make sense of O_RDONLY = 0?
Difference between "file pointer", "stream", "file descriptor" and ... "file"?
How to get the mode of a file descriptor?
https://www.gnu.org/software/libc/manual/html_node/Access-Modes.html
https://www.gnu.org/software/libc/manual/html_node/File-Status-Flags.html#File-Status-Flags
File descriptors can be duplicated. For example, when a process forks, it gets its own set of FDs that the parent doesn't affect, and the dup syscall can be used to explicitly duplicate individual FDs.
When file descriptors get duplicated, every descriptor has its own set of file descriptor flags, but they'll all share the same file status flags. For example, consider this code:
int fdA = open('/tmp/somefile', O_WRONLY);
int fdB = dup(fdA);
fcntl(fdA, F_SETFD, FD_CLOEXEC);
fcntl(fdA, F_SETFL, O_APPEND);
After running it, fdA will be close-on-exec and in append mode, and fdB will be in append mode but not close-on-exec. This is because close-on-exec is a file descriptor flag and append mode is a file status flag.
The file access mode and file creation flags are passed along with the file status flags when they're supported.
The third parameter to open, also confusingly called mode, is unrelated to everything else discussed so far. If the file is created by the call to open, then that mode is used as the permissions for the new file. Otherwise, it has no effect.
FD_CLOEXEC - file descriptor flag
O_RDONLY - file access mode
O_WRONLY - file access mode
O_RDWR - file access mode
O_CLOEXEC - file creation flag
O_CREAT - file creation flag
O_DIRECTORY - file creation flag
O_EXCL - file creation flag
O_NOCTTY - file creation flag
O_NOFOLLOW - file creation flag
O_TMPFILE - file creation flag
O_TRUNC - file creation flag
The rest of the flags you listed are file status flags.
And one final note: O_CLOEXEC is only relevant for a new FD. For existing FDs, you'll only ever use FD_CLOEXEC.
I will summarize the description by Joseph Sible-Reinstate Monica and add a few remarks on possibly confusing wording across man pages, likely the cause of the OP.
As per headings in http://man7.org/linux/man-pages/man2/fcntl.2.html (as cited in the OP) Flags = File descriptor flags + File status flags.
Remark 1: this usage of File status flags is not consistent with the rest of available information, so it should rather be called something like
Flags = File descriptor flags + Non-FD flags.
The distinction between these two groups of flags is given by Joseph Sible-Reinstate Monica.
As per http://man7.org/linux/man-pages/man2/open.2.html,
Non-FD Flags = Access mode + File creation flags + File status flags
Note that:
The man page does not use the name Non-FD Flags. It simply calls this flags, as the name of the argument in the prototypes listed. But this should not be taken as if, conceptually, these flags encompass all flags since File descriptor flags are not included.
"The distinction between these two groups of flags is that the file creation flags affect the semantics of the open operation itself, while the file status flags affect the semantics of subsequent I/O operations." [ref]
This is the most common usage of File status flags.
This is the basic classification of "entities".
Remark 2: I use quotes since the general use of flags is quite misleading.
Access mode are not flags in the usual sense, and this is clarified in
How to make sense of O_RDONLY = 0?.
Remark 3:
GNU uses a different naming, adding to the confusion.
The translation POSIX.1 <-> GNU is shown below.
Usage of File Status Flags in GNU may be especially confusing.
POSIX.1 GNU
Non-FD Flags* File Status Flags
Access modes Access mode
File creation flags Open-time Flags
File status flags Operating Modes
As for the listings enumerating each category, they are given by Joseph Sible-Reinstate Monica.
GNU also has its own Access modes, File creation flags (Open-time Flags) and File status flags (Operating Modes).

How to receive file pointer from kernel space by giving file pointer from user space

From user space
FILE* fd1 = fopen("./log/log1.txt","r");
syscall(338, fd1);
I tried
SYSCALL_DEFINE1(get_class, struct file *, fd)
But didn’t work!
How to add a tag to fd1 in kernel system?

How can we use .txt file as command line input in c++ language on a windows machine?

I want to make my c++ file read input from one text file and save output in another text file. This is to check my competitive programming questions.
I think this solution works for you.
#include <iostream>
#include <fstream>
//#define cin fin
//#define cout fout
using namespace std;
int main(){
//ofstream fout("output.txt");
//ifstream fin("input.txt");
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++){
cin>>arr[i];
}
for(int i=0;i<n;i++){
cout<<arr[i]<<endl;
}
return 0;
}
If you want to use as standard input output then you can use as it is. As per your problem you can use it by only removing two slashes(comments).
In the above program "input.txt" is file name for taking input an "output.txt" is the file in which output will be stored.
Note: You only have to provide "input.txt" the program will automatically generate "output.txt".
You can rename "input.txt" and "output.txt" as per your requirement.
If you are not satisfied with the above solution then you can use a program named hightail. Hightail is an automatic tester for programming contest. To know more about hightail and its working click here.
Unclear of what you are asking. Since your question and your description seems asking two different situations.
For your question, you seems to ask how to input a command (like dir or systeminfo) from a file. You can use the function system() in the header file stdlib.h to execute the command read from that file.
For your description, you seems to ask how to input some data from a file to stdin and output to another file, you can look for command redirection, for example Redirect Windows cmd stdout and stderr to a single file.

What cmd can I use to find all (text) files whose name is of some form in a directory?

I would like to write a bash script that runs a .cpp program on a number of text files (I'll henceforth refer to those text files as input files). The .cpp program assumes that there is an input text file in the same directory level called "input.txt". However, the inputs I would like to run through the program are in a sub-directory and there are more than one input txt files that I would like to run through the program.
The input txt files are named using the following convention:
input1.txt, input2.txt, input3.txt, etc,...
They are placed in a folder called "myInputs" which contains text files with similar name e.g., input1.txt.Sol that I'm not interested in.
The commands I would like to have in my script should look in 'myInputs' for txt files of the form: input%.txt where % may be a number. For each file of that form, the script should print out the name of the file on a line-by-line basis. i.e., input1.txt should be on its own line, input2.txt should be on it own line.
Any tip is appreciated!
There is a bash command called find
http://unixhelp.ed.ac.uk/CGI/man-cgi?find
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
(void)system( "find \"MyInputs\" \"input*.txt\"" );
/* whatever comes next */
return 0;
}
Unfortunately, I don't know that much C++, but here's a snippet in C

Where do I set the Xcode IDE property to read a data file to avoid No such file or directory

This is not a code question but an Xcode IDE question.
For those who pride themselves in code analysis, that's good, but in this case, please try to focus on the question in the Title above not the code.
In the Xcode IDE I created a new project and selected a "Command Line Tool" creating ReadAFile.
I then entered some simple code into main.c to read and display the contents of "Data.txt".
I then selected File, New, File, and selected Empty (For an empty document) and named it Data.txt and then I typed out a sentence then saved the file.
In Xcode, when I choose Product, Run, I get the following error:
Error while opening the file.
: No such file or directory
Program ended with exit code: 1
Where do I set the Xcode IDE property so that it knows where my data file is to avoid getting the "No such file or directory" error?
When I enter the very same code into ReadAFile.c and I type out the very same file "Data.txt" at a terminal prompt using vim, save it, and run make ReadAFile, the code executes properly.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char * argv[]) {
char ch, file_name[25];
FILE *fp;
strcpy(file_name,"Data.txt");
fp = fopen(file_name,"r");
if( fp == NULL ) {
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name);
while( ( ch = fgetc(fp) ) != EOF )
printf("%c",ch);
fclose(fp);
return 0;
}
That's a good question... I have a temporary, work around, answer...
I do respect your request to focusing on the question rather than your code.
As a quick temporary answer, the only answer I have for you at this point is to modify your code, for now, if you are only debugging your code along with your data file. I know hard coding your file locations is a no-no but for debugging purposes the following will get you over this bump in your road. You can try to hard code the directory location along with your data file so that your code can find it. For example, let's say that your Users directory on your Mac is jerryletter, you could copy your Data.txt file to your Users directory ~/jerryletter. Then could modify just one line of your code like the following:
"strcpy(file_name,"/Users/jerryletter/Data.txt");"
DougPan.com

Resources