1、使用系统调用open read write,完成一个C语言程序:该程序接收两个参数,参数1作为要读写的文件,参数2作为标志位,标识是读还是写。功能完成对参数1所示文件的读写,该文件的内容为 “20009200666 MYFILE”,2、 改造上面的程序,使用semaphore,并利用该程序生成2个进程,这两个进程写同一个文件,要求:a.互斥写,即只有一个进程写完后,才能让另一个进程写; b. 一个进程写入内容:“666PROC1 MYFILE1”;另一个进程写入内容:“666PROC2 MYFILE2”
时间: 2024-02-21 18:57:15 浏览: 19
下面是第一个问题的答案:
```c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s file r|w\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *file = argv[1];
const char mode = argv[2][0];
int fd = open(file, mode == 'r' ? O_RDONLY : O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
char buf[32];
ssize_t nread;
if (mode == 'r') {
nread = read(fd, buf, sizeof(buf) - 1);
if (nread == -1) {
perror("read");
exit(EXIT_FAILURE);
}
buf[nread] = '\0';
printf("%s\n", buf);
} else {
snprintf(buf, sizeof(buf), "%s%s", mode == 'w' ? "writing" : "appending", file);
ssize_t nwritten = write(fd, buf, sizeof(buf) - 1);
if (nwritten == -1) {
perror("write");
exit(EXIT_FAILURE);
}
}
if (close(fd) == -1) {
perror("close");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
```
下面是第二个问题的答案:
```c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <errno.h>
#define SEM_NAME "/my_sem"
#define SHM_NAME "/my_shm"
#define SHM_SIZE 4096
int main(int argc, char *argv[]) {
int fd = open("myfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
if (lseek(fd, SHM_SIZE - 1, SEEK_SET) == -1) {
perror("lseek");
exit(EXIT_FAILURE);
}
if (write(fd, "", 1) == -1) {
perror("write");
exit(EXIT_FAILURE);
}
void *shm = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
sem_t *sem = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0666, 1);
if (sem == SEM_FAILED) {
if (errno == EEXIST) {
sem = sem_open(SEM_NAME, O_RDWR, 0666);
}
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// Child process
for (int i = 0; i < 10; i++) {
sem_wait(sem);
char *buf = (char *)shm;
snprintf(buf, SHM_SIZE, "666PROC1 MYFILE1\n");
printf("PROC1 wrote: %s", buf);
sem_post(sem);
sleep(1);
}
exit(EXIT_SUCCESS);
} else {
// Parent process
pid_t pid2 = fork();
if (pid2 == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid2 == 0) {
// Child process
for (int i = 0; i < 10; i++) {
sem_wait(sem);
char *buf = (char *)shm;
snprintf(buf, SHM_SIZE, "666PROC2 MYFILE2\n");
printf("PROC2 wrote: %s", buf);
sem_post(sem);
sleep(1);
}
exit(EXIT_SUCCESS);
} else {
// Parent process
int status;
waitpid(pid, &status, 0);
waitpid(pid2, &status, 0);
if (sem_close(sem) == -1) {
perror("sem_close");
exit(EXIT_FAILURE);
}
if (sem_unlink(SEM_NAME) == -1) {
perror("sem_unlink");
exit(EXIT_FAILURE);
}
if (munmap(shm, SHM_SIZE) == -1) {
perror("munmap");
exit(EXIT_FAILURE);
}
if (close(fd) == -1) {
perror("close");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
}
}
```
这个程序使用了共享内存和信号量,共享内存用于两个进程之间的通信,信号量用于互斥访问共享内存。为了实现互斥访问,我们使用了一个二元信号量,初始值为 1,每个进程在访问共享内存之前都需要等待信号量,访问结束后释放信号量。这样就保证了同一时刻只有一个进程在访问共享内存。
程序使用了 mmap 函数将文件映射到内存中,这样就可以直接访问文件内容而不需要使用 read 和 write 函数。同时,程序使用了 fork 函数创建了两个进程,这两个进程共享同一个文件,每个进程在写入文件时都需要等待信号量,以保证互斥访问。每个进程写入的内容都不同,这样就可以验证两个进程的并发访问。