多线程的write和read
作者:互联网
对于write和read,由于缓冲区不足或者中断等问题,可能导致读不完或写不完,这也是为什么write和read分别返回的是成功的字节数的原因。所以书中给出了另一种操作readn和writen,保证了读写的完整性,但不保证原子性。
ssize_t /* Read "n" bytes from a descriptor */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = static_cast<char *>(vptr);
nleft = n;
while (nleft > 0)
{
if ((nread = read(fd, ptr, nleft)) < 0)
{
if (errno = EINTR) //the read is interrupted by signal
nread = 0; //call readn() again
else
return -1; /* error, return amount read so far */
}
else if (nread == 0)
{
break; /* EOF */
}
nleft -= nread;
ptr += nread;
}
return (n - nleft); /* return >= 0 */
}
ssize_t /* Write "n" bytes to a descriptor */
writen(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = static_cast<char *>(vptr);
nleft = n;
while (nleft > 0)
{
if ((nwritten = write(fd, ptr, nleft)) <= 0)
{
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /*call write again */
else
return (-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return (n - nleft); /* return >= 0 */
}
在再探Linux内核write系统调用操作的原子性这篇文章中说了,write和read一次,可以保证是原子操作,因为Linux系统内部是对其上锁了的,同时APUE P63介绍了另一种原子操作pread和pwrite。
下面我们看一下write和read的操作的原子性
1、两个线程分别操作同一个文件。
#include <bits/stdc++.h>
#include <initializer_list>
#include <unistd.h>
#include <functional>
#include <stdio.h>
#include "threadpool/threadpool.h"
#include <unistd.h>
#include<stdio.h>
#include<error.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<iostream>
#include<string.h>
using namespace std;
void test3(string input)
{
int fd=open("test.txt",O_RDWR);
//int fd=open("test.txt",O_RDWR|O_APPEND);
char fa[input.size()+1];
strcpy(fa,input.c_str());
int num=write(fd,fa,strlen(fa));//这里写的是fa长度
cout<<"write number: "<<num<<endl;
close(fd);
}
int main()
{
threadpool::ThreadPool tt;//线程池
string s1(2000000,'1');
string s2(2000000,'2');
tt.AddTask(test3,s1);
tt.AddTask(test3,s2);
getchar();
return 0;
}
(1)直接写
int fd=open("test.txt",O_RDWR);
要么全是1,要么全是2
(2)追加写
int fd=open("test.txt",O_RDWR|O_APPEND);
要么是1111…22222,要么是22222…11111,不会出现交错
总结1
对于文件描述符,映射到Linux同一个文件指针,write和read都是原子操作
2、两个线程分别操作同一个文件描述符。
效果和上面情况类似
标签:include,read,write,fd,nleft,多线程,ptr 来源: https://blog.csdn.net/weixin_43353102/article/details/118861945