#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>int main() { int p1, p2, i; FILE *fp; fp = fopen("to_be_locked.txt", "w+"); if (fp == NULL) { printf("Fail to create file"); exit(-1); } while ((p1 = fork()) == -1); if (p1 == 0) { // 子进程p1 fclose(fp); // 关闭不需要的文件描述符 fp = fopen("to_be_locked.txt", "a"); // 重新打开文件 lockf(fileno(fp), 1, 0); // 加锁 for (i = 0; i < 10; i++) fprintf(fp, "daughter %d\n", i); lockf(fileno(fp), 0, 0); // 解锁 fclose(fp); } else { while ((p2 = fork()) == -1); if (p2 == 0) { // 子进程p2 fclose(fp); fp = fopen("to_be_locked.txt", "a"); lockf(fileno(fp), 1, 0); for (i = 0; i < 10; i++) fprintf(fp, "son %d\n", i); lockf(fileno(fp), 0, 0); fclose(fp); } else { // 父进程 wait(NULL); // 等待子进程p1完成 wait(NULL); // 等待子进程p2完成 lockf(fileno(fp), 1, 0); for (i = 0; i < 10; i++) fprintf(fp, "parent %d\n", i); lockf(fileno(fp), 0, 0); fclose(fp); } } return 0;}
时间: 2024-03-11 19:46:05 浏览: 21
这段代码是一个简单的并发程序,它通过创建进程的方式,实现对同一个文件的加锁操作,从而保证文件写入的完整性。具体的实现过程如下:
1. 打开一个文件,如果打开失败,则退出程序。
. 创建两个子进程p1和p2,父进程则等待这两个子进程的结束。
3. 在子进程p1和p2中,先关闭文件描述符,然后重新打开文件,并对文件进行加锁,这样其他进程就无法同时对文件进行写入操作。
4. 子进程p1和p2分别向文件中写入自己的数据。
5. 写入完毕后,对文件进行解锁操作,然后关闭文件。
6. 父进程在等待子进程p1和p2执行完毕后,对文件进行加锁操作,并向文件中写入自己的数据。
7. 最后对文件进行解锁操作,并关闭文件。
在这个程序中,通过对文件进行加锁和解锁操作,实现了对文件的互斥访问,避免了数据的错误写入和丢失。
相关问题
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main( ) { int fd[2]; char buf[30], s[30]; pipe(fd); //创建管道 while((fork()) == -1); //创建子程序失败时,循环 if(fork() == 0) //子进程返回 { sprintf(buf, "This is an example\n"); //将 buf 中字符写入管道 write(fd[1], buf, sizeof(buf)); //将 buf 中字符写入管道 } else //父进程返回 { wait(0); //等待子程序结束 read(fd[0], s, sizeof(s)); //父进程读管道中字符 printf("%s", s); //输出读取到的字符 } return 0; }改良以上程序
以上程序是一个简单的管道通信例子,可以通过管道将一个字符串从子进程传递给父进程并输出。以下是对程序的改良:
1. 错误处理:以上程序没有进行错误处理,可以在创建管道和创建子进程时添加错误处理语句。
2. 参数传递:以上程序只传递了一个字符串,可以通过参数传递实现更加灵活的通信。
3. 程序退出:以上程序没有使用 exit() 函数退出程序,可以添加退出语句以保证程序正常结束。
改良后的程序如下所示:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
int fd[2];
char buf[30], s[30];
if (pipe(fd) == -1) { //创建管道失败
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid == -1) { //创建子进程失败
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid == 0) { //子进程返回
if (close(fd[0]) == -1) { //关闭管道读端
perror("close");
exit(EXIT_FAILURE);
}
sprintf(buf, "%s\n", argv[1]); //将参数写入管道
if (write(fd[1], buf, sizeof(buf)) == -1) { //将 buf 中字符写入管道
perror("write");
exit(EXIT_FAILURE);
}
if (close(fd[1]) == -1) { //关闭管道写端
perror("close");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
else { //父进程返回
if (close(fd[1]) == -1) { //关闭管道写端
perror("close");
exit(EXIT_FAILURE);
}
if (read(fd[0], s, sizeof(s)) == -1) { //父进程读管道中字符
perror("read");
exit(EXIT_FAILURE);
}
printf("%s", s); //输出读取到的字符
if (close(fd[0]) == -1) { //关闭管道读端
perror("close");
exit(EXIT_FAILURE);
}
wait(NULL); //等待子程序结束
exit(EXIT_SUCCESS);
}
return 0;
}
```
改良后的程序增加了错误处理和参数传递功能,程序退出时使用了 exit() 函数。
/* Socket head file */ #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h>/*sockaddr_in{}*/ #include<arpa/inet.h> /* Unix standard head file */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include <errno.h>/* strerror(),perror(),errno head file*/ #include <sys/time.h> #include <sys/wait.h> #define MAXBUFF 1024 #define PORT 9999怎么改成windows系统
在Windows系统中,网络编程需要使用Winsock API,因此需要引入`<winsock2.h>`头文件。此外,需要在程序中调用`WSAStartup()`函数和`WSACleanup()`函数来初始化和释放Winsock库。
下面是在Windows系统下进行网络编程的头文件和常量定义示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#define MAXBUFF 1024
#define PORT 9999
```
其中,`<ws2tcpip.h>`头文件包含了一些网络编程相关的函数和结构体定义。`#pragma comment(lib, "Ws2_32.lib")`语句用于链接Winsock库。
需要注意的是,在Windows系统中,端口号的类型为`unsigned short`,而不是`int`。因此,定义端口号常量时应该使用`USHORT`类型:
```c
#define PORT (USHORT)9999
```