Linux文件I/O与进程权限编程解析

1、编写一个程序,使用标准文件I/O系统调用(open()和lseek())以及off_t数据类型,实现创建大文件的功能。在编译程序时将_FILE_OFFSET_BITS宏设置为64,并进行测试以证明可以成功创建大文件。

以下是修改后的程序代码:

#define _FILE_OFFSET_BITS 64
#include <sys/stat.h>
#include <fcntl.h>
#include "tlpi_hdr.h"

int
main(int argc, char *argv[])
{
    int fd;
    off_t off;

    if (argc != 3 || strcmp(argv[1], "--help") == 0)
        usageErr("%s pathname offset\n", argv[0]);

    fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    if (fd == -1)
        errExit("open");

    off = atoll(argv[2]);
    if (lseek(fd, off, SEEK_SET) == -1)
        errExit("lseek");

    if (write(fd, "test", 4) == -1)
        errExit("write");

    exit(EXIT_SUCCESS);
}

编译时使用命令 cc -D_FILE_OFFSET_BITS=64 prog.c 进行编译,然后运行程序,例如 ./a.out x 10111222333 ,最后使用 ls -l x 查看文件大小,验证是否成功创建大文件。

2、编写一个程序,使用 O_APPEND 标志打开一个现有文件进行写入,然后在写入一些数据之前将文件指针移动到文件开头。数据会出现在文件的什么位置?为什么?

数据会出现在文件末尾。因为使用 O_APPEND 标志打开文件时,内核会保证每次写入操作都自动追加到文件末尾,即便在写入前使用 lseek 函数将文件偏移量设置到文件开头,写入操作依然会在文件末尾进行。

3、本练习旨在展示以 O_APPEND 标志打开文件所保证的原子性为何必要。编写一个程序,最多接受三个命令行参数:$ atomic_append 文件名 字节数 [x]。该程序应打开指定的文件名(必要时创建它),通过一次写入一个字节的方式向文件追加指定字节数的数据。默认情况下,程序应以 O_APPEND 标志打开文件,但如果提供了第三个命令行参数(x),则应省略 O_APPEND 标志,而是在每次写入之前执行 lseek(fd, 0, SEEK_END) 调用。同时运行该程序的两个实例,不使用 x 参数,向同一个文件写入 100 万个字节:$ atomic_append f1 1000000 & atomic_append f1 1000000。对另一个不同的文件重复相同步骤,但这次指定 x 参数:$ atomic_append f2 1000000 x & atomic_append f2 1000000 x。使用 ls –l 列出文件 f1 和 f2 的大小并解释差异。

源代码发行版中的 fileio/atomic_append.c 文件提供了解决方案。运行程序后,使用 ls -l f1 f2 查看文件大小,示例结果如下:

$ ls -l f1 f2
-rw------- 1 mtk users 2000000 Jan 9 11:14 f1
-rw------- 1 mtk users 1999962 Jan 9 11:14 f2

由于 lseek() write() 的组合不是原子操作,程序的一个实例有时会覆盖另一个实例写入的字节。因此,文件 f2 包含的字节数少于 200 万。

4、使用 fcntl() 以及必要时使用 close() 来实现 dup() 和 dup2()。(可以忽略 dup2() 和 fcntl() 在某些错误情况下返回不同 errno 值这一事实。)对于 dup2(),要处理 oldfd 等于 newfd 的特殊情况。在这种情况下,需要检查 oldfd 是否有效,可通过检查 fcntl(oldfd, F_GETFL) 是否成功来实现。如果 oldfd 无效,该函数应返回 -1 并将 errno 设置为 EBADF。

dup() 的实现:

fd = fcntl(oldfd, F_DUPFD, 0);

dup2() 的实现:

if (oldfd == newfd) {
    if (fcntl(oldfd, F_GETFL) == -1) {
        errno = EBADF;
        fd = -1;
    } else {
        fd = oldfd;
    }
} else {
    close(newfd);
    fd = fcntl(oldfd, F_DUPFD, newfd);
}

5、编译一个包含约 10 MB 数组(mbuf)的程序,使用“ls –l”列出其可执行文件大小。发现可执行文件比数组大小小得多,为什么会这样?

数组 mbuf 属于未初始化的数据段。当程序存储在磁盘上时,无需为未初始化的数据分配空间,可执行文件只需记录未初始化数据段所需的位置和大小,该空间在运行时由程序加载器分配,所以可执行文件比数组大小小得多。

6、一个具有以下用户 ID 的进程是否具有特权?请解释你的答案。实际用户 ID = 0,有效用户 ID = 1000,保存的用户 ID = 1000,文件系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值