程式寫日誌檔案時該不該加鎖

2021-10-01 19:17:26 字數 3516 閱讀 7916

**搜尋

我們這裡說的當然是伺服器日誌,也就是  server log 。

一般寫入 log 都會遵循以下步驟:

fclose(fd)

解釋一下上面的**:

1. int fd = open(path) 

會通過系統呼叫開啟乙個檔案描述符,或者在其他語言中也可以稱作資源描述符,資源型別,或控制代碼。

原子性意味著 seek 和 write 會同時執行,不會有兩個執行緒產生交叉,必須 a 執行緒執行完 seek 和 write ,b 執行緒才能繼續執行(這裡說執行緒,是因為執行緒才是 cpu 排程的基本單位)。

3. fclose(fd)

關閉描述符。

linux 一般對開啟的檔案描述符有乙個最大數量的限制,如果不關閉描述符,很有可能造成大 bug。

檢視 linux 中限制的方法如下(其中 open files 代表可以開啟的檔案數量):

於是,懷疑是因為 file_put_contents 的底層實現沒有實現原子性。

跟進原始碼(非 php 程式設計師或者對 php 底層原始碼無興趣的可以跳過了):

file_put_contents 底層實現: 

//

file.c

/* }

break

;...}//

php_streams.h

phpapi ssize_t _php_stream_write(php_stream *stream, const

char *buf, size_t count);

#define php_stream_write_string(stream, str) _php_stream_write(stream, str, strlen(str))

#define php_stream_write(stream, buf, count) _php_stream_write(stream, (buf), (count))

phpapi ssize_t _php_stream_write(php_stream *stream, const

char *buf, size_t count)

else

if(bytes)

return

bytes;}/*

writes a buffer directly to a stream, using multiple of the chunk size

*/static ssize_t _php_stream_write_buffer(php_stream *stream, const

char *buf, size_t count)

return

didwrite;

}buf +=justwrote;

count -=justwrote;

didwrite +=justwrote;

/*only screw with the buffer if we can seek, otherwise we lose data

* buffered from fifos and sockets

*/if (stream->ops->seek && (stream->flags & php_stream_flag_no_seek) == 0) }

}//php_streams.h

/*operations on streams that are file-handles

*/typedef

struct

_php_stream_ops php_stream_ops; //

static ssize_t php_stdiop_write(php_stream *stream, const

char *buf, size_t count)

bytes_written = _write(data->fd, buf, (unsigned int

)count);

#else

ssize_t bytes_written = write(data->fd, buf, count);

#endif

if (bytes_written < 0

)

if (errno ==eintr)

php_error_docref(null, e_notice,

"write of %zu bytes failed with errno=%d %s

", count, errno, strerror(errno));

}return

bytes_written;

} else

data->last_op = 'w'

;#endif

return (ssize_t) fwrite(buf, 1, count, data->file);}}

這個函式最終呼叫的是函式 php_stdiop_write 

函式 _php_stream_write_buffer 中會將字串分成多個 chunksize ,每個 chunksize 為 8192 (8k) 位元組,分別進行 write。

如果不加鎖,那麼超過 8192 位元組之後,多個程序寫日誌就會出現混亂。

而且,php 文件也說明了:

所以,最終需要根據不同的語言,具體分析。

寫日誌檔案

region 寫日誌檔案 寫日誌檔案,儲存到指定的檔案 日誌內容 儲存到檔案 public static void writerlog string log,string filename catch 讀取模板檔案返回檔案內容 public static string readtemplatefil...

linux寫日誌檔案

呼叫errorlog 函式可以向指定的logfile檔案中寫入自定義的結構體error message型別的資料 include include include include include include struct error message typedef struct error mes...

多執行緒程式寫日誌時遇到加鎖的問題

前段時間在做專案時,系統是個多執行緒程式,幾個執行緒都需要寫日誌,主線程和通訊線程經常在寫日誌時打架,為了解決這個問題,考慮在寫日誌的方法中加鎖。如下 寫日誌時加鎖 private static object m lock new object 寫日誌檔案的介面函式,此函式只向指定的檔案寫入字串 i...