看着raycp师傅的文章分析,只剩最后两个函数了fwrite、fclose
源码样例
#include<stdio.h> #include<stdlib.h> int main(){ char *data=malloc(0x1000); FILE*fp=fopen("test","wb"); fwrite(data,1,0x30,fp); return 0; }
源码分析
进入fwrite看看
29 _IO_size_t 30 _IO_fwrite (const void *buf, _IO_size_t size, _IO_size_t count, _IO_FILE *fp) 31 { 32 _IO_size_t request = size * count; 33 _IO_size_t written = 0; 34 CHECK_FILE (fp, 0); 35 if (request == 0) 36 return 0; 37 _IO_acquire_lock (fp); 38 if (_IO_vtable_offset (fp) != 0 || _IO_fwide (fp, -1) == -1) 39 written = _IO_sputn (fp, (const char *) buf, request); 40 _IO_release_lock (fp); 41 /* We have written all of the input in case the return value indicates 42 this or EOF is returned. The latter is a special case where we 43 simply did not manage to flush the buffer. But the data is in the 44 buffer and therefore written as far as fwrite is concerned. */ 45 if (written == request || written == EOF) 46 return count; 47 else 48 return written / size; 49 } 50 libc_hidden_def (_IO_fwrite)
函数通过简单的检查后,就进入了_IO_sputn函数
1278 _IO_size_t 1279 _IO_new_file_xsputn (_IO_FILE *f, const void *data, _IO_size_t n) 1280 { 1281 const char *s = (const char *) data; 1282 _IO_size_t to_do = n; 1283 int must_flush = 0; 1284 _IO_size_t count = 0; 1285 1286 if (n <= 0) 1287 return 0; 1288 /* This is an optimized implementation. 1289 If the amount to be written straddles a block boundary 1290 (or the filebuf is unbuffered), use sys_write directly. */ 1291 1292 /* First figure out how much space is available in the buffer. */ 1293 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) 1294 { 1295 count = f->_IO_buf_end - f->_IO_write_ptr; 1296 if (count >= n) 1297 { 1298 const char *p; 1299 for (p = s + n; p > s; ) 1300 { 1301 if (*--p == ' ') 1302 { 1303 count = p - s + 1; 1304 must_flush = 1; 1305 break; 1306 } 1307 } 1308 } 1309 } 1310 else if (f->_IO_write_end > f->_IO_write_ptr) 1311 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */ 1312 1313 /* Then fill the buffer. */ 1314 if (count > 0) 1315 { 1316 if (count > to_do) 1317 count = to_do; 1318 #ifdef _LIBC 1319 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count); 1320 #else 1321 memcpy (f->_IO_write_ptr, s, count); 1322 f->_IO_write_ptr += count; 1323 #endif 1324 s += count; 1325 to_do -= count; 1326 } 1327 if (to_do + must_flush > 0) 1328 { 1329 _IO_size_t block_size, do_write; 1330 /* Next flush the (full) buffer. */ 1331 if (_IO_OVERFLOW (f, EOF) == EOF) 1332 /* If nothing else has to be written we must not signal the 1333 caller that everything has been written. */ 1334 return to_do == 0 ? EOF : n - to_do; 1335 1336 /* Try to maintain alignment: write a whole number of blocks. */ 1337 block_size = f->_IO_buf_end - f->_IO_buf_base; 1338 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0); 1339 1340 if (do_write) 1341 { 1342 count = new_do_write (f, s, do_write); 1343 to_do -= count; 1344 if (count < do_write) 1345 return n - to_do; 1346 } 1347 1348 /* Now write out the remainder. Normally, this will fit in the 1349 buffer, but it's somewhat messier for line-buffered files, 1350 so we let _IO_default_xsputn handle the general case. */ 1351 if (to_do) 1352 to_do -= _IO_default_xsputn (f, s+do_write, to_do); 1353 } 1354 return n - to_do; 1355 } 1356 libc_hidden_ver (_IO_new_file_xsputn, _IO_file_xsputn)
由于还没对缓冲区进行初始化_IO_write_base、_IO_write_ptr、_IO_write_end、_IO_buf_base、_IO_buf_end都是0,所以需要对其进行初始化,所以进入了这里,我们跟进_IO_doallocbuf看一看
► 818 if (f->_IO_write_base == NULL) 819 { 820 _IO_doallocbuf (f); 821 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base); 822 }
_IO_doallocbuf函数
这个函数跟我们在fread里的函数是一样的,其主要作用是将_IO_buf_base、_IO_buf_end初始化,我们可以看下此时的f指针即可,接着进入了_IO_setg函数