关于linux中进程打开同一文件操作的一点分析

本文深入探讨了Linux中进程如何打开同一文件及其操作特性,包括每个进程的独立偏移和共享状态的区别,通过实验证明了父子进程间与不同进程间的文件偏移行为。
关于linux中进程打开同一文件操作的一点分析

按照系统的设计,每个进程自己维护一张打开表
 索引  文件描述符     文件指针
 0      close_on_exec   0x.....
 .............
然后内核会维护一张表,这个表表示所有打开的文件,每个文件一行不会重复。
里面存储有文件的当前状态,也就是为什么有进程锁定后,其他进程不能写。状态值就是写在这里的。
然后内核说虽然多个进程打开同一文件仅仅是指向了同一个索引位置,但是每个进程却有自己独立的偏移。
于是我做了2个测试。
1)父子进程之间
2)无关联的2个进程之间
-------------------------------------------------------------
代码如下:
 1 #include "apue.h"
  2 #include <fcntl.h>
  3
  4 int main(void)
  5 {
  6  int fd;
  7  off_t off = 0;
  8  pid_t pid = 0;
  9  const char * file = "add2";
 10  fd = open(file, O_RDONLY);
 11  off = lseek(fd, 10, SEEK_CUR);
 12  printf("current process %d, offset %d\n", getpid(), off);
 13  sleep(100);
 14 /* pid = fork();
 15  if ( pid > 0)
 16  {
 17    waitpid(pid);
 18    off = lseek(fd, 0, SEEK_CUR);
 19    printf("current process %d, offset %d\n", getpid(), off);
 20    exit(0);
 21  }
 22  else if ( pid == 0)
 23  {
 24   printf("current process %d, offset %d\n", getpid(), off);
 25  off = lseek(fd,10, SEEK_CUR);  
 26  sleep(5);
 27  } */
 28  return 0;



----------------------------------------------------------------------
结论:
情况1 父子进程之间  文件偏移像是一个共享的字段,不论谁修改了读取的都是最新的值,可能原因是子进程复制了父进程所有东西的时候,有的还不是完全复制
情况2 不同进程之间  结论成立,每个进程即便是打开了同一文件,仍然有自己独立的文件偏移
确保多个进程同一文件进行 `fprintf` 操作时的安全性,可采用以下方法: #### 文件锁机制 使用文件锁能防止多个进程同时对文件进行写入操作,保证数据的完整性。在 Linux 系统中,可使用 `flock` 或 `fcntl` 函数来实现文件锁。 以下是使用 `flock` 函数的示例代码: ```c #include <stdio.h> #include <sys/file.h> #include <unistd.h> int main() { FILE *fp = fopen("test.txt", "a"); if (fp == NULL) { perror("fopen"); return 1; } // 加锁 if (flock(fileno(fp), LOCK_EX) == -1) { perror("flock"); fclose(fp); return 1; } // 进行 fprintf 操作 fprintf(fp, "This is a test from a process.\n"); fflush(fp); // 解锁 if (flock(fileno(fp), LOCK_UN) == -1) { perror("flock"); } fclose(fp); return 0; } ``` #### 原子操作 `O_APPEND` 标志可确保每次写入操作都是原子的,即使多个进程同时写入,也不会覆盖彼此的数据。在打开文件时使用该标志,示例如下: ```c #include <stdio.h> #include <fcntl.h> #include <unistd.h> int main() { int fd = open("test.txt", O_WRONLY | O_APPEND | O_CREAT, 0666); if (fd == -1) { perror("open"); return 1; } FILE *fp = fdopen(fd, "a"); if (fp == NULL) { perror("fdopen"); close(fd); return 1; } // 进行 fprintf 操作 fprintf(fp, "This is a test from a process.\n"); fflush(fp); fclose(fp); return 0; } ``` #### 进程间同步机制 使用信号量、互斥锁等进程间同步机制,确保同一时间只有一个进程能够对文件进行写入操作。例如,使用 POSIX 信号量: ```c #include <stdio.h> #include <semaphore.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> int main() { sem_t *sem = sem_open("/my_semaphore", O_CREAT, 0666, 1); if (sem == SEM_FAILED) { perror("sem_open"); return 1; } // 等待信号量 if (sem_wait(sem) == -1) { perror("sem_wait"); sem_close(sem); return 1; } FILE *fp = fopen("test.txt", "a"); if (fp == NULL) { perror("fopen"); sem_post(sem); sem_close(sem); return 1; } // 进行 fprintf 操作 fprintf(fp, "This is a test from a process.\n"); fflush(fp); fclose(fp); // 释放信号量 if (sem_post(sem) == -1) { perror("sem_post"); } sem_close(sem); sem_unlink("/my_semaphore"); return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值