1

这是我的一个未解决的考试问题。两个 Unix 进程可以同时写入单个文件中的不同位置吗?

  1. 是的,这两个进程会有自己的文件表条目
  2. 不,共享 i 节点包含一个偏移量指针
  3. 只有一个进程有写权限
  4. 是的,但前提是我们使用 NFS 进行操作
4

3 回答 3

3
  • inode 中没有记录文件偏移量,因此答案 2. 不正确。
  • 没有记录的理由让进程修改其访问权限,因此 3. 是不正确的。
  • NFS 允许不同主机上的进程同时访问,这里的问题是针对同一主机上的进程,因此 NFS 不应该有所作为。

这是一个 shell 脚本,演示了剩下的答案 1. 是正确的:

# create a 10m file
dd if=/dev/zero of=/var/tmp/file bs=1024k count=10

# create two 1 MB files
cd /tmp
printf "aaaaaaaa" > aa
printf "bbbbbbbb" > bb
i=0
while [ $i -lt 17 ]; do
  cat aa aa > aa.new && mv aa.new aa
  cat bb bb > bb.new && mv bb.new bb
  i=$((i+1))
done

ls -lG /var/tmp/file /tmp/aa /tmp/bb

# launch 10 processes that will write at different locations in the same file.
# Uses dd notrunc option for the file not to be truncated
# Uses GNU dd fdatasync option for unbuffered writes

i=0
while [ $i -lt 5 ]; do
  (
  dd if=/tmp/aa of=/var/tmp/file conv=notrunc,fdatasync bs=1024k count=1 seek=$((i*2)) 2>/dev/null &
  dd if=/tmp/bb of=/var/tmp/file conv=notrunc,fdatasync bs=1024k count=1 seek=$((i*2+1)) 2>/dev/null &
  ) &
  i=$((i+1))
done

# Check concurrency
printf "\n%d processes are currently writing to /var/tmp/file\n" "$(fuser /var/tmp/file 2>/dev/null | wc -w)"

# Wait for write completion and check file contents
wait
printf "/var/tmp/file contains:\n"
od -c /var/tmp/file

它的输出显示十个进程成功并同时写入同一个文件:

-rw-r--r-- 1 jlliagre  1048576 oct.  30 08:25 /tmp/aa
-rw-r--r-- 1 jlliagre  1048576 oct.  30 08:25 /tmp/bb
-rw-r--r-- 1 jlliagre 10485760 oct.  30 08:25 /var/tmp/file

10 processes are currently writing to /var/tmp/file

/var/tmp/file contains:
0000000   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a
*
4000000   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b
*
10000000   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a
*
14000000   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b
*
20000000   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a
*
24000000   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b
*
30000000   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a
*
34000000   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b
*
40000000   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a   a
*
44000000   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b   b
*
50000000
于 2013-10-30T07:28:14.090 回答
2

定义

是的,这两个进程将有自己的文件表条目。

如果使用 open 函数打开文件两次,则创建两个文件描述符。

每个文件描述符都有单独的文件状态标志。

所以这两个文件描述符有一个写权限,文件描述符 1 和文件描述符 2 的初始位置指向文件的第一个字符。

如果我们为描述符和写入文件指定某个位置,则可以轻松测试它。

file.txt 的内容

我叫钱德鲁。这是一个空文件。

测试编码:

#include<stdio.h>                                                                           
#include<fcntl.h>
#include<stdlib.h>


 main()
 {
    int fd1, fd2;

 if((fd1=open("file.txt", O_WRONLY)) <0){
            perror("Error");
            exit(0);
    }
    if((fd2=open("file.txt", O_WRONLY)) < 0) {
            perror("Error");
            exit(0);
    }
    if(lseek(fd1,20,SEEK_SET) != 20)
    {
            printf("Cannot seek\n");
            exit(0);
    }
    if(write(fd1,"testing",7) != 7)
    {
            printf("Error write\n");
            exit(0);
    }
    if(lseek(fd2,10,SEEK_SET) != 10)
    {
            printf("Cannot seek\n");
            exit(0);
    }
    if(write(fd2,"condition",9) != 9)
    {
            printf("Error write\n");
            exit(0);
    }
  }

输出:之后我的输出是

我的名字是conditionitesting 空文件。

于 2013-10-30T07:59:06.570 回答
1

是的,他们当然可以,但需要注意以下几点:

  • 根据open()模式,一个进程可以轻松擦除文件内容
  • 根据调度,写操作的顺序是不确定的
  • 没有强制锁定(通常) - 仔细的设计需要咨询锁定。
  • 如果他们使用缓冲 I/O 写入同一区域,结果可能是不确定的。
于 2013-10-29T22:19:57.237 回答