Mencipta perisian teguh melibatkan membuat pilihan reka bentuk yang disengajakan yang memudahkan penyelenggaraan kod dan melanjutkan fungsi. Satu contoh sedemikian ialah melaksanakan fungsi pengelogan dalam aplikasi C. Pembalakan bukan hanya tentang mencetak mesej ralat; ia mengenai membina sistem berstruktur yang menyokong penyahpepijatan, analisis dan juga keserasian merentas platform.
Dalam artikel ini, kami akan meneroka cara membina sistem pengelogan langkah demi langkah menggunakan corak reka bentuk dan amalan terbaik, yang diilhamkan oleh senario dunia sebenar. Pada akhirnya, anda akan mempunyai pemahaman yang kukuh tentang mencipta sistem pembalakan yang fleksibel dan boleh diperluaskan dalam C.
Jadual Kandungan
- Keperluan untuk Pembalakan
- Menyusun Fail untuk Pengelogan
- Mencipta Fungsi Pengelogan Pusat
- Melaksanakan Penapis Modul Perisian
- Menambah Pembalakan Bersyarat
- Mengurus Sumber Dengan Betul
- Memastikan Keselamatan Benang
- Konfigurasi Luaran dan Dinamik
- Pemformatan Log Tersuai
- Pengendalian Ralat Dalaman
- Prestasi dan Kecekapan
- Amalan Terbaik Keselamatan
- Menyepadukan dengan Alat Pengelogan
- Pengujian dan Pengesahan
- Pengelogan Fail Merentas Platform
- Membungkus Semuanya
- Tambahan
Keperluan untuk Pembalakan
Bayangkan mengekalkan sistem perisian yang digunakan di tapak terpencil. Setiap kali isu timbul, anda mesti melakukan perjalanan secara fizikal untuk menyahpepijat masalah itu. Persediaan ini dengan cepat menjadi tidak praktikal kerana penyebaran skala secara geografi. Pembalakan boleh menjimatkan hari.
Pengelogan menyediakan akaun terperinci tentang keadaan dalaman sistem pada titik kritikal semasa pelaksanaan. Dengan memeriksa fail log, pembangun boleh mendiagnosis dan menyelesaikan isu tanpa mengeluarkannya secara langsung. Ini amat berguna untuk ralat sporadis yang sukar dicipta semula dalam persekitaran terkawal.
Nilai pembalakan menjadi lebih jelas dalam aplikasi berbilang benang, di mana ralat mungkin bergantung pada masa dan keadaan perlumbaan. Menyahpepijat isu ini tanpa log memerlukan usaha yang ketara dan alatan khusus, yang mungkin tidak selalu tersedia. Log menawarkan gambaran tentang apa yang berlaku, membantu menentukan punca punca.
Walau bagaimanapun, pengelogan bukan sekadar ciri mudah—ia adalah sistem. Mekanisme pengelogan yang dilaksanakan dengan baik boleh membawa kepada isu prestasi, kelemahan keselamatan dan kod yang tidak dapat diselenggara. Oleh itu, mengikut pendekatan dan corak berstruktur adalah penting semasa mereka bentuk sistem pembalakan.
Menyusun Fail untuk Pengelogan
Organisasi fail yang betul adalah penting untuk memastikan pangkalan kod anda dapat diselenggara semasa ia berkembang. Pengelogan, sebagai fungsi yang berbeza, harus diasingkan ke dalam modulnya sendiri, menjadikannya mudah untuk dikesan dan diubah suai tanpa menjejaskan bahagian kod yang tidak berkaitan.
Fail pengepala (logger.h):
#ifndef LOGGER_H #define LOGGER_H #include <stdio.h> #include <time.h> // Function prototypes void log_message(const char* text); #endif // LOGGER_H </time.h></stdio.h>
Fail pelaksanaan (logger.c):
#include "logger.h" void log_message(const char* text) { if (!text) { fprintf(stderr, "Invalid log message\n"); return; } time_t now = time(NULL); printf("[%s] %s\n", ctime(&now), text); }
Penggunaan (utama.c):
#include "logger.h" int main() { log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); return 0; }
Menyusun dan Menjalankan:
Untuk menyusun dan menjalankan contoh, gunakan arahan berikut dalam terminal anda:
gcc -o app main.c logger.c ./app
Keluaran Jangkaan:
[Mon Sep 27 14:00:00 2021 ] Application started [Mon Sep 27 14:00:00 2021 ] Performing operation... [Mon Sep 27 14:00:00 2021 ] Operation completed.
Langkah pertama ialah mencipta direktori khusus untuk pengelogan. Direktori ini harus menempatkan semua fail pelaksanaan yang berkaitan. Sebagai contoh, logger.c boleh mengandungi logik teras sistem pengelogan anda, manakala logger_test.c boleh mengadakan ujian unit. Menyimpan fail berkaitan bersama meningkatkan kejelasan dan kerjasama dalam pasukan pembangunan.
Selain itu, antara muka pengelogan hendaklah didedahkan melalui fail pengepala, seperti logger.h, diletakkan dalam direktori yang sesuai, seperti termasuk/ atau direktori yang sama dengan fail sumber anda. Ini memastikan modul lain yang memerlukan keupayaan pengelogan boleh mengaksesnya dengan mudah. Mengekalkan fail pengepala berasingan daripada fail pelaksanaan turut menyokong pengkapsulan, menyembunyikan butiran pelaksanaan daripada pengguna API pengelogan.
Akhir sekali, menggunakan konvensyen penamaan yang konsisten untuk direktori dan fail anda meningkatkan lagi kebolehselenggaraan. Contohnya, menggunakan logger.h dan logger.c menjelaskan bahawa fail ini tergolong dalam modul pengelogan. Elakkan daripada mencampurkan kod yang tidak berkaitan ke dalam modul pengelogan, kerana ini menggagalkan tujuan pemodulatan.
Mencipta Fungsi Pembalakan Pusat
Di tengah-tengah mana-mana sistem pembalakan terletak fungsi pusat yang mengendalikan operasi teras: merekodkan mesej log. Fungsi ini harus direka bentuk dengan mengambil kira kesederhanaan dan kebolehlanjutan untuk menyokong peningkatan pada masa hadapan tanpa memerlukan perubahan besar.
Pelaksanaan (logger.c):
#include "logger.h" #include <stdio.h> #include <time.h> #include <assert.h> #define BUFFER_SIZE 256 static_assert(BUFFER_SIZE >= 64, "Buffer size is too small"); void log_message(const char* text) { char buffer[BUFFER_SIZE]; time_t now = time(NULL); if (!text) { fprintf(stderr, "Error: Null message passed to log_message\n"); return; } snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text); printf("%s", buffer); } </assert.h></time.h></stdio.h>
Nota: Penggunaan static_assert memerlukan C11 atau lebih baru. Pastikan pengkompil anda menyokong standard ini.
Fungsi pengelogan asas boleh dimulakan dengan mencetak mesej ke output standard. Menambah cap masa pada setiap entri log meningkatkan kegunaannya dengan menyediakan konteks temporal. Sebagai contoh, log boleh membantu mengenal pasti apabila ralat tertentu berlaku atau cara peristiwa berlaku dari semasa ke semasa.
Untuk memastikan modul pengelogan tidak berstatus, elakkan daripada mengekalkan sebarang keadaan dalaman antara panggilan fungsi. Pilihan reka bentuk ini memudahkan pelaksanaan dan memastikan modul berfungsi dengan lancar dalam persekitaran berbilang benang. Modul stateless juga lebih mudah untuk diuji dan nyahpepijat kerana kelakuannya tidak bergantung pada interaksi terdahulu.
Pertimbangkan pengendalian ralat semasa mereka bentuk fungsi pengelogan. Sebagai contoh, apa yang berlaku jika penunjuk NULL diluluskan sebagai mesej log? Mengikuti "Prinsip Samurai", fungsi itu harus sama ada mengendalikan perkara ini dengan baik atau gagal serta-merta, menjadikan penyahpepijatan lebih mudah.
Melaksanakan Penapis Modul Perisian
Apabila aplikasi berkembang dalam kerumitan, output pengelogan mereka boleh menjadi luar biasa. Tanpa penapis, log daripada modul yang tidak berkaitan mungkin membanjiri konsol, menjadikannya sukar untuk menumpukan pada maklumat yang berkaitan. Melaksanakan penapis memastikan bahawa hanya log yang dikehendaki direkodkan.
Untuk mencapai matlamat ini, perkenalkan mekanisme untuk menjejak modul yang didayakan. Ini mungkin semudah senarai global atau secanggih jadual cincang yang diperuntukkan secara dinamik. Senarai ini menyimpan nama modul dan hanya log daripada modul ini diproses.
Penapisan dilaksanakan dengan menambahkan parameter modul pada fungsi pengelogan. Sebelum menulis log, fungsi menyemak sama ada modul didayakan. Jika tidak, ia melangkau entri log. Pendekatan ini memastikan keluaran pembalakan padat dan tertumpu pada bidang yang diminati. Berikut ialah contoh pelaksanaan penapisan:
Fail Pengepala (logger.h):
#ifndef LOGGER_H #define LOGGER_H #include <stdio.h> #include <time.h> // Function prototypes void log_message(const char* text); #endif // LOGGER_H </time.h></stdio.h>
Fail Pelaksanaan (logger.c):
#include "logger.h" void log_message(const char* text) { if (!text) { fprintf(stderr, "Invalid log message\n"); return; } time_t now = time(NULL); printf("[%s] %s\n", ctime(&now), text); }
Pelaksanaan ini menyeimbangkan antara kesederhanaan dan kefungsian, menyediakan titik permulaan yang kukuh untuk pengelogan khusus modul.
Menambah Pembalakan Bersyarat
Pengelogan bersyarat adalah penting untuk mencipta sistem fleksibel yang menyesuaikan diri dengan persekitaran atau keadaan masa jalan yang berbeza. Sebagai contoh, semasa pembangunan, anda mungkin memerlukan log nyahpepijat verbose untuk mengesan gelagat aplikasi. Dalam pengeluaran, anda mungkin lebih suka mencatatkan amaran dan ralat sahaja untuk meminimumkan overhed prestasi.
Satu cara untuk melaksanakan ini ialah dengan memperkenalkan tahap log. Tahap biasa termasuk DEBUG, INFO, AMARAN dan RALAT. Fungsi pengelogan boleh mengambil parameter tambahan untuk tahap log, dan log direkodkan hanya jika tahapnya memenuhi atau melebihi ambang semasa. Pendekatan ini memastikan mesej yang tidak berkaitan ditapis, memastikan log ringkas dan berguna.
Untuk menjadikan ini boleh dikonfigurasikan, anda boleh menggunakan pembolehubah global untuk menyimpan ambang peringkat log. Aplikasi kemudiannya boleh melaraskan ambang ini secara dinamik, seperti melalui fail konfigurasi atau arahan masa jalan.
Fail Pengepala (logger.h):
#include "logger.h" int main() { log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); return 0; }
Fail Pelaksanaan (logger.c):
gcc -o app main.c logger.c ./app
Pelaksanaan ini memudahkan untuk mengawal verbositi pembalakan. Sebagai contoh, anda boleh menetapkan tahap log kepada DEBUG semasa sesi penyelesaian masalah dan mengembalikannya kepada AMARAN dalam pengeluaran.
Menguruskan Sumber dengan Betul
Pengurusan sumber yang betul adalah penting, terutamanya apabila berurusan dengan operasi fail atau berbilang destinasi pembalakan. Gagal menutup fail atau membebaskan memori yang diperuntukkan boleh menyebabkan kebocoran sumber, merendahkan prestasi sistem dari semasa ke semasa.
Pastikan mana-mana fail yang dibuka untuk pembalakan ditutup dengan betul apabila ia tidak diperlukan lagi. Ini boleh dicapai dengan melaksanakan fungsi untuk memulakan dan menutup sistem pembalakan.
Pelaksanaan (logger.c):
#ifndef LOGGER_H #define LOGGER_H #include <stdio.h> #include <time.h> // Function prototypes void log_message(const char* text); #endif // LOGGER_H </time.h></stdio.h>
Penggunaan (utama.c):
#include "logger.h" void log_message(const char* text) { if (!text) { fprintf(stderr, "Invalid log message\n"); return; } time_t now = time(NULL); printf("[%s] %s\n", ctime(&now), text); }
Menyusun dan Menjalankan:
#include "logger.h" int main() { log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); return 0; }
Ini akan menulis mesej log ke application.log. Dengan menyediakan fungsi init_logging dan close_logging, anda memberikan kawalan aplikasi ke atas kitaran hayat sumber pembalakan, mencegah kebocoran dan isu akses.
Memastikan Keselamatan Benang
Dalam aplikasi berbilang benang, fungsi pengelogan mestilah selamat benang untuk mengelakkan keadaan perlumbaan dan memastikan mesej log tidak tersilang atau rosak.
Satu cara untuk mencapai keselamatan benang ialah dengan menggunakan mutex atau mekanisme penyegerakan lain.
Pelaksanaan (logger.c):
gcc -o app main.c logger.c ./app
Penggunaan dalam Persekitaran Berbilang Thread (utama.c):
[Mon Sep 27 14:00:00 2021 ] Application started [Mon Sep 27 14:00:00 2021 ] Performing operation... [Mon Sep 27 14:00:00 2021 ] Operation completed.
Menyusun dan Menjalankan:
#include "logger.h" #include <stdio.h> #include <time.h> #include <assert.h> #define BUFFER_SIZE 256 static_assert(BUFFER_SIZE >= 64, "Buffer size is too small"); void log_message(const char* text) { char buffer[BUFFER_SIZE]; time_t now = time(NULL); if (!text) { fprintf(stderr, "Error: Null message passed to log_message\n"); return; } snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text); printf("%s", buffer); } </assert.h></time.h></stdio.h>
Ini memastikan bahawa log daripada urutan yang berbeza tidak mengganggu antara satu sama lain, mengekalkan integriti mesej log.
Konfigurasi Luaran dan Dinamik
Membenarkan konfigurasi pengelogan ditetapkan secara luaran meningkatkan fleksibiliti. Konfigurasi seperti tahap log, modul yang didayakan dan destinasi boleh dimuatkan daripada fail konfigurasi atau ditetapkan melalui argumen baris arahan.
Fail Konfigurasi (config.cfg):
#ifndef LOGGER_H #define LOGGER_H #include <stdbool.h> void enable_module(const char* module); void disable_module(const char* module); void log_message(const char* module, const char* text); #endif // LOGGER_H </stdbool.h>
Pelaksanaan (logger.c):
#include "logger.h" #include <stdio.h> #include <string.h> #define MAX_MODULES 10 #define MODULE_NAME_LENGTH 20 static char enabled_modules[MAX_MODULES][MODULE_NAME_LENGTH]; void enable_module(const char* module) { for (int i = 0; i #ifndef LOGGER_H #define LOGGER_H typedef enum { DEBUG, INFO, WARNING, ERROR } LogLevel; void set_log_level(LogLevel level); void log_message(LogLevel level, const char* module, const char* text); #endif // LOGGER_H </string.h></stdio.h>') { strncpy(enabled_modules[i], module, MODULE_NAME_LENGTH - 1); enabled_modules[i][MODULE_NAME_LENGTH - 1] = '
#include "logger.h" #include <stdio.h> #include <time.h> #include <string.h> static LogLevel current_log_level = INFO; void set_log_level(LogLevel level) { current_log_level = level; } void log_message(LogLevel level, const char* module, const char* text) { if (level '; break; } } } void disable_module(const char* module) { for (int i = 0; i #include "logger.h" #include <stdio.h> #include <stdlib.h> static FILE* log_file = NULL; void init_logging(const char* filename) { if (filename) { log_file = fopen(filename, "a"); if (!log_file) { fprintf(stderr, "Failed to open log file: %s\n", filename); exit(EXIT_FAILURE); } } else { log_file = stdout; // Default to standard output } } void close_logging() { if (log_file && log_file != stdout) { fclose(log_file); log_file = NULL; } } void log_message(const char* text) { if (!log_file) { fprintf(stderr, "Logging not initialized.\n"); return; } time_t now = time(NULL); fprintf(log_file, "[%s] %s\n", ctime(&now), text); fflush(log_file); // Ensure the message is written immediately } </stdlib.h></stdio.h></string.h></time.h></stdio.h>'; break; } } } static int is_module_enabled(const char* module) { for (int i = 0; i
Penggunaan (utama.c):
#include "logger.h" int main() { init_logging("application.log"); log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); close_logging(); return 0; }
Menyusun dan Menjalankan:
gcc -o app main.c logger.c ./app
Dengan melaksanakan konfigurasi dinamik, anda boleh melaraskan gelagat pengelogan tanpa menyusun semula aplikasi, yang amat berguna dalam persekitaran pengeluaran.
Pemformatan Log Tersuai
Memperibadikan format mesej log boleh menjadikannya lebih bermaklumat dan lebih mudah untuk dihuraikan, terutamanya apabila menyepadukan dengan alat analisis log.
Pelaksanaan (logger.c):
#include "logger.h" #include <pthread.h> static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; void log_message(const char* text) { pthread_mutex_lock(&log_mutex); // Existing logging code if (!log_file) { fprintf(stderr, "Logging not initialized.\n"); pthread_mutex_unlock(&log_mutex); return; } time_t now = time(NULL); fprintf(log_file, "[%s] %s\n", ctime(&now), text); fflush(log_file); pthread_mutex_unlock(&log_mutex); } </pthread.h>
Sampel Output:
#include "logger.h" #include <pthread.h> void* thread_function(void* arg) { char* thread_name = (char*)arg; for (int i = 0; i <p>Untuk pengelogan berstruktur, pertimbangkan untuk mengeluarkan log dalam format JSON:<br> </p> <pre class="brush:php;toolbar:false">gcc -pthread -o app main.c logger.c ./app
Format ini sesuai untuk menghuraikan menggunakan alatan pengurusan log.
Pengendalian Ralat Dalaman
Sistem pengelogan itu sendiri mungkin menghadapi ralat, seperti gagal membuka fail atau isu dengan peruntukan sumber. Adalah penting untuk mengendalikan ralat ini dengan anggun dan memberikan maklum balas kepada pembangun.
Pelaksanaan (logger.c):
#ifndef LOGGER_H #define LOGGER_H #include <stdio.h> #include <time.h> // Function prototypes void log_message(const char* text); #endif // LOGGER_H </time.h></stdio.h>
Dengan menyemak keadaan sumber sebelum digunakan dan memberikan mesej ralat yang bermakna, anda boleh mengelakkan ranap dan membantu dalam menyelesaikan masalah dengan sistem pengelogan itu sendiri.
Prestasi dan Kecekapan
Pengelogan boleh menjejaskan prestasi aplikasi, terutamanya jika pengelogan dilakukan secara meluas atau dilakukan secara serentak. Untuk mengurangkan perkara ini, pertimbangkan teknik seperti penimbalan log atau melaksanakan operasi pembalakan secara tidak segerak.
Pelaksanaan Pengelogan Asynchronous (logger.c):
#include "logger.h" void log_message(const char* text) { if (!text) { fprintf(stderr, "Invalid log message\n"); return; } time_t now = time(NULL); printf("[%s] %s\n", ctime(&now), text); }
Penggunaan (utama.c):
#include "logger.h" int main() { log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); return 0; }
Menggunakan pengelogan tak segerak mengurangkan masa utas aplikasi utama menghabiskan pengelogan, meningkatkan prestasi keseluruhan.
Amalan Terbaik Keselamatan
Log secara tidak sengaja boleh mendedahkan maklumat sensitif, seperti kata laluan atau data peribadi. Adalah penting untuk mengelakkan pengelogan maklumat sedemikian dan untuk melindungi fail log daripada akses yang tidak dibenarkan.
Pelaksanaan (logger.c):
gcc -o app main.c logger.c ./app
Menetapkan Kebenaran Fail:
[Mon Sep 27 14:00:00 2021 ] Application started [Mon Sep 27 14:00:00 2021 ] Performing operation... [Mon Sep 27 14:00:00 2021 ] Operation completed.
Cadangan:
- Sanitasi Input: Pastikan data sensitif tidak disertakan dalam mesej log.
- Kawalan Akses: Tetapkan kebenaran yang sesuai pada fail log untuk menyekat akses.
- Penyulitan: Pertimbangkan untuk menyulitkan fail log jika ia mengandungi maklumat sensitif.
- Putaran Log: Laksanakan putaran log untuk mengelakkan log berkembang selama-lamanya dan untuk menguruskan pendedahan.
Dengan mengikuti amalan ini, anda meningkatkan keselamatan aplikasi anda dan mematuhi peraturan perlindungan data.
Mengintegrasikan dengan Alat Pembalakan
Aplikasi moden sering disepadukan dengan alatan dan perkhidmatan pengelogan luaran untuk pengurusan dan analisis log yang lebih baik.
Integrasi Syslog (logger.c):
#include "logger.h" #include <stdio.h> #include <time.h> #include <assert.h> #define BUFFER_SIZE 256 static_assert(BUFFER_SIZE >= 64, "Buffer size is too small"); void log_message(const char* text) { char buffer[BUFFER_SIZE]; time_t now = time(NULL); if (!text) { fprintf(stderr, "Error: Null message passed to log_message\n"); return; } snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text); printf("%s", buffer); } </assert.h></time.h></stdio.h>
Penggunaan (utama.c):
#ifndef LOGGER_H #define LOGGER_H #include <stdbool.h> void enable_module(const char* module); void disable_module(const char* module); void log_message(const char* module, const char* text); #endif // LOGGER_H </stdbool.h>
Perkhidmatan Pembalakan Jauh:
Untuk menghantar log ke perkhidmatan jauh seperti Graylog atau Elasticsearch, anda boleh menggunakan soket rangkaian atau perpustakaan khusus.
Contoh menggunakan soket (logger.c):
#include "logger.h" #include <stdio.h> #include <string.h> #define MAX_MODULES 10 #define MODULE_NAME_LENGTH 20 static char enabled_modules[MAX_MODULES][MODULE_NAME_LENGTH]; void enable_module(const char* module) { for (int i = 0; i #ifndef LOGGER_H #define LOGGER_H typedef enum { DEBUG, INFO, WARNING, ERROR } LogLevel; void set_log_level(LogLevel level); void log_message(LogLevel level, const char* module, const char* text); #endif // LOGGER_H </string.h></stdio.h>') { strncpy(enabled_modules[i], module, MODULE_NAME_LENGTH - 1); enabled_modules[i][MODULE_NAME_LENGTH - 1] = '
#include "logger.h" #include <stdio.h> #include <time.h> #include <string.h> static LogLevel current_log_level = INFO; void set_log_level(LogLevel level) { current_log_level = level; } void log_message(LogLevel level, const char* module, const char* text) { if (level '; break; } } } void disable_module(const char* module) { for (int i = 0; i #include "logger.h" #include <stdio.h> #include <stdlib.h> static FILE* log_file = NULL; void init_logging(const char* filename) { if (filename) { log_file = fopen(filename, "a"); if (!log_file) { fprintf(stderr, "Failed to open log file: %s\n", filename); exit(EXIT_FAILURE); } } else { log_file = stdout; // Default to standard output } } void close_logging() { if (log_file && log_file != stdout) { fclose(log_file); log_file = NULL; } } void log_message(const char* text) { if (!log_file) { fprintf(stderr, "Logging not initialized.\n"); return; } time_t now = time(NULL); fprintf(log_file, "[%s] %s\n", ctime(&now), text); fflush(log_file); // Ensure the message is written immediately } </stdlib.h></stdio.h></string.h></time.h></stdio.h>'; break; } } } static int is_module_enabled(const char* module) { for (int i = 0; i
Penggunaan (utama.c):
#include "logger.h" int main() { init_logging("application.log"); log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); close_logging(); return 0; }
Integrasi dengan alatan luaran boleh menyediakan ciri lanjutan seperti pengurusan log terpusat, pemantauan masa nyata dan amaran.
Pengujian dan Pengesahan
Ujian menyeluruh memastikan sistem pengelogan berfungsi dengan betul dalam pelbagai keadaan.
Contoh Ujian Unit (test_logger.c):
gcc -o app main.c logger.c ./app
Menyusun dan Menjalankan Ujian:
#include "logger.h" #include <pthread.h> static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; void log_message(const char* text) { pthread_mutex_lock(&log_mutex); // Existing logging code if (!log_file) { fprintf(stderr, "Logging not initialized.\n"); pthread_mutex_unlock(&log_mutex); return; } time_t now = time(NULL); fprintf(log_file, "[%s] %s\n", ctime(&now), text); fflush(log_file); pthread_mutex_unlock(&log_mutex); } </pthread.h>
Strategi Pengujian:
- Ujian Unit: Sahkan fungsi individu.
- Ujian Tekanan: Simulasikan pengelogan frekuensi tinggi.
- Ujian Berbilang Thread: Log daripada berbilang urutan serentak.
- Suntikan Kegagalan: Simulasikan ralat seperti cakera penuh atau kegagalan rangkaian.
Dengan menguji sistem pembalakan dengan teliti, anda boleh mengenal pasti dan membetulkan isu sebelum ia menjejaskan persekitaran pengeluaran.
Pengelogan Fail Merentas Platform
Keserasian merentas platform adalah keperluan untuk perisian moden. Walaupun contoh sebelumnya berfungsi dengan baik pada sistem berasaskan Unix, ia mungkin tidak berfungsi pada Windows kerana perbezaan dalam API pengendalian fail. Untuk menangani perkara ini, anda memerlukan mekanisme pengelogan merentas platform.
Pelaksanaan (logger.c):
#ifndef LOGGER_H #define LOGGER_H #include <stdio.h> #include <time.h> // Function prototypes void log_message(const char* text); #endif // LOGGER_H </time.h></stdio.h>
Penggunaan (logger.c):
#include "logger.h" void log_message(const char* text) { if (!text) { fprintf(stderr, "Invalid log message\n"); return; } time_t now = time(NULL); printf("[%s] %s\n", ctime(&now), text); }
Dengan mengasingkan butiran khusus platform, anda memastikan logik pengelogan utama kekal bersih dan konsisten.
Membungkus Semuanya
Merancang sistem pengelogan mungkin kelihatan seperti tugas yang mudah pada pandangan pertama, tetapi seperti yang telah kita lihat, ia melibatkan banyak keputusan yang memberi kesan kepada fungsi, prestasi dan kebolehselenggaraan. Dengan menggunakan corak reka bentuk dan pendekatan berstruktur, anda boleh mencipta sistem pengelogan yang teguh, boleh diperluas dan mudah untuk disepadukan.
Daripada menyusun fail kepada melaksanakan keserasian merentas platform, setiap langkah dibina berdasarkan langkah sebelumnya untuk membentuk keseluruhan yang padu. Sistem ini boleh menapis log mengikut modul, melaraskan verbositi melalui tahap log, menyokong berbilang destinasi dan mengendalikan sumber dengan betul. Ia memastikan keselamatan benang, membenarkan konfigurasi luaran, menyokong pemformatan tersuai dan mematuhi amalan terbaik keselamatan.
Dengan menerima corak seperti Reka Bentuk Tanpa Status, Antara Muka Dinamik dan Lapisan Abstraksi, anda mengelakkan perangkap biasa dan menjadikan pangkalan kod anda kalis masa hadapan. Sama ada anda sedang mengusahakan utiliti kecil atau aplikasi berskala besar, prinsip ini tidak ternilai.
Usaha yang anda laburkan dalam membina sistem pengelogan yang direka dengan baik membuahkan hasil dalam mengurangkan masa penyahpepijatan, cerapan yang lebih baik tentang gelagat aplikasi dan pihak berkepentingan yang lebih gembira. Dengan asas ini, anda kini dilengkapi untuk mengendalikan keperluan pembalakan walaupun projek yang paling kompleks.
Tambahan: Mempertingkatkan Sistem Pembalakan
Dalam bahagian tambahan ini, kami akan menangani beberapa bahagian untuk penambahbaikan yang dikenal pasti lebih awal untuk meningkatkan sistem pembalakan yang telah kami bina. Kami akan menumpukan pada memperhalusi ketekalan kod, menambah baik pengendalian ralat, menjelaskan konsep yang kompleks dan mengembangkan ujian dan pengesahan. Setiap topik termasuk teks pengenalan, contoh praktikal yang boleh disusun dan rujukan luaran untuk pembelajaran lanjut.
1. Ketekalan dan Pemformatan Kod
Konvensyen pemformatan kod dan penamaan yang konsisten meningkatkan kebolehbacaan dan kebolehselenggaraan. Kami akan menyeragamkan nama pembolehubah dan fungsi menggunakan snake_case, yang biasa dalam pengaturcaraan C.
Pelaksanaan Kemas Kini (logger.h):
#ifndef LOGGER_H #define LOGGER_H #include <stdio.h> #include <time.h> // Function prototypes void log_message(const char* text); #endif // LOGGER_H </time.h></stdio.h>
Pelaksanaan Kemas Kini (logger.c):
#include "logger.h" void log_message(const char* text) { if (!text) { fprintf(stderr, "Invalid log message\n"); return; } time_t now = time(NULL); printf("[%s] %s\n", ctime(&now), text); }
Penggunaan Kemas Kini (utama.c):
#include "logger.h" int main() { log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); return 0; }
Menyusun dan Menjalankan:
gcc -o app main.c logger.c ./app
Rujukan Luaran:
- Piawaian Pengekodan GNU: Konvensyen Penamaan
- Gaya Pengekodan Kernel Linux
2. Pengendalian Ralat yang Diperbaiki
Pengendalian ralat yang mantap memastikan aplikasi dapat mengendalikan situasi yang tidak dijangka dengan anggun.
Pemeriksaan Ralat Dipertingkat (logger.c):
[Mon Sep 27 14:00:00 2021 ] Application started [Mon Sep 27 14:00:00 2021 ] Performing operation... [Mon Sep 27 14:00:00 2021 ] Operation completed.
Rujukan Luaran:
- Ralat Pengendalian dalam C
- Pernyataan dalam C
3. Menjelaskan Pembalakan Asynchronous
Pengelogan tak segerak meningkatkan prestasi dengan mengasingkan proses pengelogan daripada aliran aplikasi utama. Berikut ialah penjelasan terperinci dengan contoh praktikal.
Pelaksanaan (logger.c):
#include "logger.h" #include <stdio.h> #include <time.h> #include <assert.h> #define BUFFER_SIZE 256 static_assert(BUFFER_SIZE >= 64, "Buffer size is too small"); void log_message(const char* text) { char buffer[BUFFER_SIZE]; time_t now = time(NULL); if (!text) { fprintf(stderr, "Error: Null message passed to log_message\n"); return; } snprintf(buffer, BUFFER_SIZE, "[%s] %s", ctime(&now), text); printf("%s", buffer); } </assert.h></time.h></stdio.h>
Penggunaan (utama.c):
#ifndef LOGGER_H #define LOGGER_H #include <stdbool.h> void enable_module(const char* module); void disable_module(const char* module); void log_message(const char* module, const char* text); #endif // LOGGER_H </stdbool.h>
Menyusun dan Menjalankan:
#include "logger.h" #include <stdio.h> #include <string.h> #define MAX_MODULES 10 #define MODULE_NAME_LENGTH 20 static char enabled_modules[MAX_MODULES][MODULE_NAME_LENGTH]; void enable_module(const char* module) { for (int i = 0; i #ifndef LOGGER_H #define LOGGER_H typedef enum { DEBUG, INFO, WARNING, ERROR } LogLevel; void set_log_level(LogLevel level); void log_message(LogLevel level, const char* module, const char* text); #endif // LOGGER_H </string.h></stdio.h>') { strncpy(enabled_modules[i], module, MODULE_NAME_LENGTH - 1); enabled_modules[i][MODULE_NAME_LENGTH - 1] = '
#include "logger.h" #include <stdio.h> #include <time.h> #include <string.h> static LogLevel current_log_level = INFO; void set_log_level(LogLevel level) { current_log_level = level; } void log_message(LogLevel level, const char* module, const char* text) { if (level '; break; } } } void disable_module(const char* module) { for (int i = 0; i #include "logger.h" #include <stdio.h> #include <stdlib.h> static FILE* log_file = NULL; void init_logging(const char* filename) { if (filename) { log_file = fopen(filename, "a"); if (!log_file) { fprintf(stderr, "Failed to open log file: %s\n", filename); exit(EXIT_FAILURE); } } else { log_file = stdout; // Default to standard output } } void close_logging() { if (log_file && log_file != stdout) { fclose(log_file); log_file = NULL; } } void log_message(const char* text) { if (!log_file) { fprintf(stderr, "Logging not initialized.\n"); return; } time_t now = time(NULL); fprintf(log_file, "[%s] %s\n", ctime(&now), text); fflush(log_file); // Ensure the message is written immediately } </stdlib.h></stdio.h></string.h></time.h></stdio.h>'; break; } } } static int is_module_enabled(const char* module) { for (int i = 0; i
Penjelasan:
- Model Pengeluar-Pengguna: Urutan utama menghasilkan mesej log dan menambahkannya pada baris gilir. Benang pekerja log menggunakan mesej daripada baris gilir dan menulisnya ke fail log.
- Penyegerakan Benang: Muteks dan pembolehubah keadaan memastikan akses selamat benang kepada sumber kongsi.
- Penutupan Anggun: Bendera logging_active dan pembolehubah keadaan memberi isyarat kepada benang pekerja untuk keluar apabila pembalakan ditutup.
Rujukan Luaran:
- Masalah Pengeluar-Pengguna
- Pengaturcaraan Benang POSIX
4. Memperluas Ujian dan Pengesahan
Ujian adalah penting untuk memastikan sistem pengelogan berfungsi dengan betul dalam pelbagai keadaan.
Menggunakan Rangka Kerja Ujian Perpaduan:
Perpaduan ialah rangka kerja ujian ringan untuk C.
Persediaan:
- Muat turun Unity dari repositori rasmi: Unity di GitHub
- Sertakan unity.h dalam fail ujian anda.
Fail Ujian (test_logger.c):
#include "logger.h" int main() { init_logging("application.log"); log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); close_logging(); return 0; }
Menyusun dan Menjalankan Ujian:
gcc -o app main.c logger.c ./app
Penjelasan:
- Sediakan dan TearDown: Fungsi dijalankan sebelum dan selepas setiap ujian untuk persediaan dan pembersihan.
- Pernyataan: Gunakan makro TEST_ASSERT_* untuk mengesahkan keadaan.
- Kes Ujian: Ujian meliputi pengelogan ke stdout dan ke fail.
Rujukan Luaran:
- Rangka Kerja Ujian Perpaduan
- Ujian Unit dalam C
5. Peningkatan Keselamatan
Memastikan sistem pengelogan selamat adalah penting, terutamanya apabila berurusan dengan data sensitif.
Transmisi Selamat dengan TLS:
Untuk menghantar log melalui rangkaian dengan selamat, gunakan penyulitan TLS.
Pelaksanaan Menggunakan OpenSSL (logger.c):
#ifndef LOGGER_H #define LOGGER_H #include <stdio.h> #include <time.h> // Function prototypes void log_message(const char* text); #endif // LOGGER_H </time.h></stdio.h>
Rujukan Luaran:
- Dokumentasi OpenSSL
- Pengaturcaraan Selamat dengan OpenSSL
Pematuhan terhadap Peraturan Perlindungan Data:
Apabila mengelog data peribadi, pastikan pematuhan dengan peraturan seperti GDPR.
Cadangan:
- Penanomaan: Alih keluar atau tutup pengecam peribadi dalam log.
- Kawalan Akses: Hadkan akses kepada fail log.
- Dasar Pengekalan Data: Tentukan tempoh log disimpan.
Rujukan Luaran:
- Pematuhan GDPR EU
- Peraturan Keselamatan HIPAA
6. Memanfaatkan Perpustakaan Pembalakan Sedia Ada
Kadangkala, menggunakan perpustakaan pengelogan yang mantap boleh menjimatkan masa dan menyediakan ciri tambahan.
Pengenalan kepada zlog:
zlog ialah perpustakaan pengelogan yang boleh dipercayai, selamat untuk benang dan sangat boleh dikonfigurasikan untuk C.
Ciri:
- Tatarajah melalui fail.
- Sokongan untuk berbilang kategori log dan tahap.
- Keupayaan pengelogan tak segerak.
Contoh Penggunaan:
- Pemasangan:
#include "logger.h" void log_message(const char* text) { if (!text) { fprintf(stderr, "Invalid log message\n"); return; } time_t now = time(NULL); printf("[%s] %s\n", ctime(&now), text); }
- Fail Konfigurasi (zlog.conf):
#include "logger.h" int main() { log_message("Application started"); log_message("Performing operation..."); log_message("Operation completed."); return 0; }
- Pelaksanaan (utama.c):
gcc -o app main.c logger.c ./app
- Menyusun dan Menjalankan:
[Mon Sep 27 14:00:00 2021 ] Application started [Mon Sep 27 14:00:00 2021 ] Performing operation... [Mon Sep 27 14:00:00 2021 ] Operation completed.
Rujukan Luaran:
- Tapak Web Rasmi zlog
- Projek log4c
Perbandingan dengan Pelaksanaan Tersuai:
-
Kelebihan Menggunakan Perpustakaan:
- Menjimatkan masa pembangunan.
- Menawarkan ciri lanjutan.
- Diuji dengan baik dan diselenggara.
-
Kelemahan:
- Mungkin termasuk ciri yang tidak perlu.
- Menambah kebergantungan luaran.
- Kurang kawalan ke atas kerja dalaman.
7. Mempertingkatkan Kesimpulan
Untuk mengakhirinya, mari kita perkukuhkan perkara penting dan galakkan penerokaan selanjutnya.
Pemikiran Akhir:
Membina sistem pembalakan yang mantap ialah aspek kritikal pembangunan perisian. Dengan memfokuskan pada ketekalan kod, pengendalian ralat, kejelasan, ujian, keselamatan dan memanfaatkan alatan sedia ada apabila sesuai, anda mencipta asas yang meningkatkan kebolehselenggaraan dan kebolehpercayaan aplikasi anda.
Seruan Bertindak:
- Gunakan Konsep: Sepadukan peningkatan ini ke dalam projek anda.
- Teroka Lebih Lanjut: Siasat ciri pengelogan yang lebih maju seperti alat penggiliran log, penapisan dan analisis.
- Kekal Kemas Kini: Ikuti perkembangan amalan terbaik dan teknologi baru muncul dalam pembalakan dan pembangunan perisian.
Sumber Tambahan:
- Seni Pembalakan
Atas ialah kandungan terperinci Mewujudkan Sistem Pembalakan yang Teguh dalam C. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

C Alasan penggunaan berterusan termasuk prestasi tinggi, aplikasi luas dan ciri -ciri yang berkembang. 1) Prestasi kecekapan tinggi: C melaksanakan dengan baik dalam pengaturcaraan sistem dan pengkomputeran berprestasi tinggi dengan terus memanipulasi memori dan perkakasan. 2) Digunakan secara meluas: bersinar dalam bidang pembangunan permainan, sistem tertanam, dan lain -lain. 3) Evolusi berterusan: Sejak pembebasannya pada tahun 1983, C terus menambah ciri -ciri baru untuk mengekalkan daya saingnya.

Trend pembangunan masa depan C dan XML adalah: 1) C akan memperkenalkan ciri -ciri baru seperti modul, konsep dan coroutin melalui piawaian C 20 dan C 23 untuk meningkatkan kecekapan dan keselamatan pengaturcaraan; 2) XML akan terus menduduki kedudukan penting dalam pertukaran data dan fail konfigurasi, tetapi akan menghadapi cabaran JSON dan YAML, dan akan berkembang dengan lebih ringkas dan mudah untuk menghuraikan arahan, seperti penambahbaikan XMLSChema1.1 dan XPath3.1.

Model reka bentuk C moden menggunakan ciri -ciri baru C 11 dan seterusnya untuk membantu membina perisian yang lebih fleksibel dan cekap. 1) Gunakan Ekspresi Lambda dan STD :: Fungsi untuk memudahkan corak pemerhati. 2) Mengoptimumkan prestasi melalui semantik mudah alih dan pemajuan sempurna. 3) Penunjuk pintar memastikan jenis keselamatan dan pengurusan sumber.

C Konsep teras pengaturcaraan multithreading dan serentak termasuk penciptaan dan pengurusan thread, penyegerakan dan pengecualian bersama, pembolehubah bersyarat, penyatuan thread, pengaturcaraan tak segerak, kesilapan umum dan teknik debugging, dan pengoptimuman prestasi dan amalan terbaik. 1) Buat benang menggunakan kelas STD :: Thread. Contohnya menunjukkan cara membuat dan menunggu benang selesai. 2) Segerakkan dan pengecualian bersama untuk menggunakan std :: mutex dan std :: lock_guard untuk melindungi sumber bersama dan mengelakkan persaingan data. 3) Pemboleh ubah keadaan menyedari komunikasi dan penyegerakan antara benang melalui std :: condition_variable. 4) Contoh kolam benang menunjukkan cara menggunakan kelas threadpool untuk memproses tugas selari untuk meningkatkan kecekapan. 5) Pengaturcaraan Asynchronous menggunakan std :: as

Pengurusan memori C, petunjuk dan templat adalah ciri teras. 1. Pengurusan memori secara manual memperuntukkan dan melepaskan memori melalui baru dan memadam, dan memberi perhatian kepada perbezaan antara timbunan dan timbunan. 2. Pointers membenarkan operasi langsung alamat memori, dan gunakannya dengan berhati -hati. Penunjuk pintar dapat memudahkan pengurusan. 3.

C sesuai untuk pengaturcaraan sistem dan interaksi perkakasan kerana ia menyediakan keupayaan kawalan dekat dengan perkakasan dan ciri-ciri kuat pengaturcaraan berorientasikan objek. 1) C melalui ciri-ciri peringkat rendah seperti penunjuk, pengurusan memori dan operasi bit, operasi peringkat sistem yang cekap dapat dicapai. 2) Interaksi perkakasan dilaksanakan melalui pemacu peranti, dan C boleh menulis pemandu ini untuk mengendalikan komunikasi dengan peranti perkakasan.

C sesuai untuk membina sistem permainan dan simulasi berprestasi tinggi kerana ia menyediakan dekat dengan kawalan perkakasan dan prestasi yang cekap. 1) Pengurusan memori: Kawalan manual mengurangkan pemecahan dan meningkatkan prestasi. 2) Pengoptimuman masa kompilasi: Fungsi inline dan pengembangan gelung meningkatkan kelajuan berjalan. 3) Operasi peringkat rendah: Akses langsung ke perkakasan, mengoptimumkan grafik dan pengkomputeran fizikal.

Kebenaran mengenai masalah operasi fail: Pembukaan fail gagal: Kebenaran yang tidak mencukupi, laluan yang salah, dan fail yang diduduki. Penulisan data gagal: Penampan penuh, fail tidak boleh ditulis, dan ruang cakera tidak mencukupi. Soalan Lazim Lain: Traversal fail perlahan, pengekodan fail teks yang salah, dan kesilapan bacaan fail binari.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Muat turun versi mac editor Atom
Editor sumber terbuka yang paling popular

mPDF
mPDF ialah perpustakaan PHP yang boleh menjana fail PDF daripada HTML yang dikodkan UTF-8. Pengarang asal, Ian Back, menulis mPDF untuk mengeluarkan fail PDF "dengan cepat" dari tapak webnya dan mengendalikan bahasa yang berbeza. Ia lebih perlahan dan menghasilkan fail yang lebih besar apabila menggunakan fon Unicode daripada skrip asal seperti HTML2FPDF, tetapi menyokong gaya CSS dsb. dan mempunyai banyak peningkatan. Menyokong hampir semua bahasa, termasuk RTL (Arab dan Ibrani) dan CJK (Cina, Jepun dan Korea). Menyokong elemen peringkat blok bersarang (seperti P, DIV),

MantisBT
Mantis ialah alat pengesan kecacatan berasaskan web yang mudah digunakan yang direka untuk membantu dalam pengesanan kecacatan produk. Ia memerlukan PHP, MySQL dan pelayan web. Lihat perkhidmatan demo dan pengehosan kami.

Dreamweaver Mac版
Alat pembangunan web visual

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma