gpt4 book ai didi

c - dup 系统调用的奇怪行为

转载 作者:太空宇宙 更新时间:2023-11-04 01:18:50 27 4
gpt4 key购买 nike

因此,我阅读了有关 Linux 中的文件 I/O 的内容,并想尝试一下。然而,我在代码中遇到了两个奇怪的行为,我正在努力寻找它们的原因。

/*
* This program shows the usage of dup and dup2 functions
*/

#include "creep.h"
#include <fcntl.h>

#define BUFSIZE 2048

int main(int argc, char *argv[]) {

int fd, dup_fd, n;
char buf[BUFSIZE], buff[BUFSIZE];
if (argc != 2)
err_quit("Usage: dup <filename>\n");

fd = open(argv[1], O_RDWR);

while ((n = read(fd, buf, BUFSIZE)) > 0)
if (write(STDOUT_FILENO, buf, n) != n)
err_sys("write error");

if (n < 0)
err_sys("read error");

dup_fd = dup(fd);

while ((n = read(dup_fd, buff, BUFSIZE)) > 0)
if (write(STDOUT_FILENO, buff, n) != n)
err_sys("write error");

if (n < 0)
err_sys("read error");

printf("\nValues are : %d and %d\n", fd, dup_fd);

close(fd);
exit(0);
}

现在,当我运行这个程序时:-

# ./dup dup.c

它实际上只打印文件一次,而不是针对第二个重复的描述符。

我对上面的内容进行了跟踪,希望找出正在发生的事情,但我只能看到这个 ->

open("dup.c", O_RDWR)                   = 3
read(3, "/*\n * This program shows the usa"..., 2048) = 708
write(1, "/*\n * This program shows the usa"..., 708/
------------omitting the file from trace-------------
read(3, "", 2048) = 0
dup(3) = 4
read(4, "", 2048) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f170112d000
write(1, "\n", 1
) = 1
write(1, "Values are : 3 and 4\n", 21Values are : 3 and 4
) = 21
close(3)

第一次在 fd 上进行读/写调用时,缓冲区中有文件内容,这有点奇怪。但是对于 dup_fd,缓冲区是空的。我不知道为什么会这样。以前,我两次都使用相同的缓冲区,我认为我应该使用单独的缓冲区,但无济于事。

我读到 dup 函数给出了最小编号的可用文件描述符,它是原始文件描述符的副本。在进程表条目中的文件指针指向文件描述符的同一文件表的意义上是重复的。

为什么我无法读取具有重复文件描述符的文件。我做错了什么吗?

creep.h 头文件:-

/*
* My own header, to be included before all standard system headers written by me.
*/
#ifndef _CREEP_H
#define _CREEP_H

#define _POSIX_C_SOURCE 200809L

#if defined(SOLARIS)
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 700
#endif

#include <sys/types.h> /* some systems will require this */
#include <sys/stat.h>
#include <sys/termios.h> /* for winsize */

#if defined(MACOS) || !defined(TIOCGWINSZ)
#include <sys/ioctl.h>
#endif

#include <stdio.h> /* for convenience */
#include <stdlib.h> /* for convenience */
#include <stddef.h> /* for offsetof */
#include <string.h> /* for convenience */
#include <unistd.h> /* for convenience */
#include <signal.h> /* for SIG_ERR */
#include <errno.h> /* for definition of errno */
#include <stdarg.h> /* ISO C variable arguments */
#include <syslog.h> /* for convenience */


#define MAXLINE 4096 /* max line length */

/*
* Default file access permissions for new files.
*/
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

/*
* Default permissions for new directories.
*/
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | SIXOTH)

typedef void Sigfunc(int); /* for signal handlers */

#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))

/*
* Prototypes for my own functions.
*/
char *path_alloc(size_t *);
long open_max(void);

int set_cloexec(int);
void clr_fl(int, int);
void set_fl(int, int);

void pr_exit(int);

void pr_mask(const char *);
Sigfunc *signal_intr(int, Sigfunc *);

void daemonize(const char *);

void sleep_us(unsigned int);
ssize_t readn(int, void *, size_t);
ssize_t writen(int, const void *, size_t);

int fd_pipe(int *);
int recv_fd(int, ssize_t (*func) (int, const void *, size_t));
int send_fd(int, int);
int send_err(int, int, const char *);
int serv_listen(const char *);
int serv_accept(int, uid_t *);
int cli_conn(const char *);
int buf_args(char *, int (*func)(int, char **));
int tty_cbreak(int);
int tty_raw(int);
int tty_reset(int);
void tty_atexit(void);
struct termios *tty_termios(void);

int ptym_open(char *, int);
int ptys_open(char *);
#ifdef TIOCGWINSZ
pid_t pty_fork(int *, char *, int, const struct termios *, const struct winsize *);
#endif

int lock_reg(int, int, int, off_t, int, off_t);

#define read_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
#define readw_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
#define write_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
#define writew_lcok(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
#define un_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))

pid_t lock_test(int, int, off_t, int, off_t);

#define is_read_lockable(fd, offset, whence, len) \
(lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)
#define is_write_lockable(fd, offset, whence, len) \
(lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0)

void err_msg(const char *, ...);
void err_dump(const char *, ...) __attribute__((noreturn));
void err_quit(const char *, ...) __attribute__((noreturn));
void err_cont(int, const char *, ...);
void err_exit(int, const char *, ...) __attribute__((noreturn));
void err_ret(const char *, ...);
void err_sys(const char *, ...) __attribute__((noreturn));

void log_msg(const char *, ...);
void log_open(const char *, int, int);
void log_quit(const char *, ...) __attribute__((noreturn));
void log_ret(const char *, ...);
void log_sys(const char *, ...) __attribute__((noreturn));
void log_exit(int, const char *, ...) __attribute__((noreturn));

void TELL_WAIT(void);
void TELL_PARENT(pid_t);
void TELL_CHILD(pid_t);
void WAIT_PARENT(void);
void WAIT_CHILD(void);

/*
* ERROR Function Definitions
*/

static void err_doit(int, int, const char *, va_list);

/*
* Nonfatal error rleated to a system call.
* Print a message and return.
*/
void err_ret(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
}

/*
* Fata error related to a system call.
* Print a message and terminate.
*/
void err_sys(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
exit(1);
}

/*
* Nonfatal error unrealted to a system call.
* Error code passed as explicit parameter.
* Print a message and return.
*/
void err_cont(int error, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(1, error, fmt, ap);
va_end(ap);
}

/*
* Fatal error unrelated to a system call.
* Error code passed as explicit parameter.
* Print a message and return.
*/
void err_exit(int error, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(1, error, fmt, ap);
va_end(ap);
exit(1);
}

/*
* Fatal error related to a system call.
* Print a message, dump core and terminate.
*/
void err_dump(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(1); /* shouldn't get here */
}

/*
* Nonfatal error unrelated to a system call.
* Print a message and return.
*/
void err_msg(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(0, 0, fmt, ap);
va_end(ap);
}

/*
* Fatale error unrelated to a system call.
* Print a message and terminate.
*/
void err_quit(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(0, 0, fmt, ap);
va_end(ap);
exit(1);
}

/*
* Print a message and return to caller.
* Caller specifies "errnoflag".
*/
static void err_doit(int errnoflag, int error, const char *fmt, va_list ap) {
char buf[MAXLINE];
vsnprintf(buf, MAXLINE-1, fmt, ap);
if (errnoflag)
snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1, ": %s", strerror(error));
strcat(buf, "\n");
fflush(stdout);
fputs(buf, stderr);
fflush(NULL);
}

#if 0
/*
* ERROR Routines for programs that can run as a Daemon.
* Commented out because of undefined reference of log_to_stderr.
*/

static void log_doit(int, int, int, const char *, va_list ap);

/*
* Caller must define and set this: nonzero if
* interactive, zero if daemon
*/
extern int log_to_stderr;

/*
* Initialize syslog(), if running as daemon.
*/
void log_open(const char *ident, int option, int facility) {
if (log_to_stderr == 0)
openlog(ident, option, facility);
}

/*
* Nonfatal error rleated to a system call.
* Print a message with the systems' errno value and return.
*/
void log_ret(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
log_doit(1, errno, LOG_ERR, fmt, ap);
va_end(ap);
}

/*
* Fata error related to a system call.
* Print a message and terminate.
*/
void log_sys(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
log_doit(1, errno, LOG_ERR, fmt, ap);
va_end(ap);
exit(2);
}

/*
* Fatal error unrelated to a system call.
* Error code passed as explicit parameter.
* Print a message and return.
*/
void log_exit(int error, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
log_doit(1, error, LOG_ERR, fmt, ap);
va_end(ap);
exit(2);
}

/*
* Nonfatal error unrelated to a system call.
* Print a message and return.
*/
void log_msg(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
log_doit(0, 0, LOG_ERR, fmt, ap);
va_end(ap);
}

/*
* Fatale error unrelated to a system call.
* Print a message and terminate.
*/
void log_quit(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
log_doit(0, 0, LOG_ERR, fmt, ap);
va_end(ap);
exit(2);
}

/*
* Print a message and return to caller.
* Caller specifies "errnoflag".
*/
static void log_doit(int errnoflag, int error, int priority, const char *fmt, va_list ap) {
char buf[MAXLINE];
vsnprintf(buf, MAXLINE-1, fmt, ap);
if (errnoflag)
snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1, ": %s", strerror(error));
strcat(buf, "\n");
if (log_to_stderr) {
fflush(stdout);
fputs(buf, stderr);
fflush(stderr);
} else {
syslog(priority, "%s", buf);
}
}

#endif


#endif /* _CREEP_H */

最佳答案

当您到达 dup 时,您的第一个循环已经结束。

为什么结束了?因为你阅读了一切。 fd 位于文件末尾。

然后你复制它。现在您有 2 个 fd 引用同一个文件对象(PO​​SIX 术语中的“打开文件描述”)。它们都在文件末尾

您需要倒带 (lseek(dup_fd, 0, SEEK_SET)) 以再次读取文件。请注意,搜索是对文件对象的操作,因此它会影响两个 fd。您可以将 fd 搜索到位置 0,然后从 dup_fd 中读取,它会再次读取内容。

您甚至可以交替调用 read(fd,...)read(dup_fd,...) 并且您仍然可以获得文件内容如果您只是在阅读时打印每个 block ,则按顺序排列。

关于c - dup 系统调用的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49560602/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com