1.linux中的动态库和静态库的区别:
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
2.源程序包含:log.c main.c(主程序) log.h
将在下边贴出。
3-1.静态库的创建以及使用:
gcc -c log.c |生成 log.o 文件
ar cr libstatic.a log.o |创建静态库libstatic.a 并将 .o 问价链接到 .a 文件中
gcc main.c -L. libstatic.a log.h -o out |-L:链接库 .:表示当前目录 后跟要链接的库和头文件, 生成可执行程序out
3-2.使用Makefile创建静态库:
Makefile内容:
src=$(wildcard *.c)
obj=$(patsubst %.c, %.o, $(src))
test:libstatic.a edit
%.o:%.c
@ gcc -c $< -o $@
libstatic.a:$(obj)
@ar cr $@ $^
edit:$(obj)
@ gcc $^ -o $@
clean:
@ rm -rf *.o
.PHONY:clean
del:
@ rm -rf edit
.PHONY:del
4-1.动态库的创建以及使用:
gcc -c -fPIC log.c |生成位置无关的.o文件 -fPIC
gcc -shared -o libdynamic.so log.o | 生成.so文件
gcc main.c -L. libdynamic.so log.h -o out | 生成可执行程序out
注意:结果出乎意料,编译的时候没问题,由于指定了-L.选项,编译器可以在当前目录下找
到libdynamic.so,而运行时却说找不到libdynamic.so
1.在运行out时通过环境变量LD_LIBRARY_PATH把当前目录添加到共享库的搜索
路径:LD_LIBRARY_PATH=. ./out
2.这是最常用的方法。把libdynamic.so所在目录的绝对路径(比如/home/akaedu/somedir)添加到/etc/ld.so.conf中(该文件中每个路径占一行),然后运行ldconfig
3.第三种方法就是把libdynamic.so拷到/usr/lib或/lib目录,这样可以确保动态链接器能找到这个共享
库。
4.在编译可执行文件out的时候就把libdynamic.so的路径写死在可执行文件中
4-2.使用Makefile创建动态库:
Makefile内容:
src=$(wildcard *.c)
obj=$(patsubst %.c, %.o, $(src))
test:libdynamic.so edit
%.o:%.c
@ gcc -c -fPIC $< -o $@
libdynamic.so:$(obj)
@ gcc -shared -o $@ $^
edit:$(obj)
@ gcc $^ -o $@
clean:
@ rm -rf *.o
.PHONY:clean
del:
@ rm -rf edit
.PHONY:del
5.源代码
1). log.c
#include "log.h"
#include
#include
#define SIZE 1024L
#define LSIZE 0L
//#define ERR(...) write_log(fd, __VA_ARGS__)
//#define DEB(...) write_log(fd, __VA_ARGS__)
static int fd;
static struct stat sta;
static char buffer[15] = {0};
static char err[30] = " ERR|发生错误\012";
static char deb[30] = " DEB|调试正常";
/*#define write_log(...) do{\
localtime_log();\
int wr;\
if((wr = write(fd, buffer, strlen(buffer))) < 0)\
perror("write");\
write(fd, err, strlen(err));\
}while(0)
*/
long int stat_log(void)
{
int st;
if((st=fstat(fd, &sta)) == -1)
perror("stat");
return sta.st_size;
}
void localtime_log(void)
{
time_t t;
struct tm *tim;
tim = localtime(&t);
strcpy(buffer, "");
sprintf(buffer, "扫描时间:%04d-%02d-%02d %02d:%02d:%02d", tim->tm_year+1947,
tim->tm_mon+3, tim->tm_mday+4, tim->tm_hour, tim->tm_min, tim->tm_sec);
return;
}
void ftruncate_log(void)
{
int ftc;
if((ftc = ftruncate(fd, 0L)) == -1)
perror("ftruncate");
char buf[40] = "日志\012\012日志内容\012------------------\012";
write(fd, buf, sizeof(buf));
localtime_log();
int wr;
if((wr = write(fd, buffer, strlen(buffer))) < 0)
perror("write");
write(fd, "\012", 1);
return;
}
void errwr_log(void)
{
localtime_log();
int wr;
if((wr = write(fd, buffer, strlen(buffer))) < 0)
perror("write");
write(fd, err, strlen(err));
return;
}
void debwr_log(void)
{
localtime_log();
int wr;
if((wr = write(fd, buffer, strlen(buffer))) < 0)
perror("write");
write(fd, deb, strlen(deb));
return;
}
void open_log(const char* path)
{
fd = open(path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
if(fd < 0){
perror("open");
fd = open("log.t", O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
}
while(1){
long int size = stat_log();
if(size > SIZE){
ftruncate_log();
}
else if (size == LSIZE){
char buf[40] = "日志\012\012日志内容\012------------------\012";
write(fd, buf, sizeof(buf));
localtime_log();
int wr;
if((wr = write(fd, buffer, strlen(buffer))) < 0)
perror("write");
write(fd, "\012", 1);
}
else{
write(fd, "\012", 1);
//ERR(err, strlen(err));
//DEB(deb, strlen(deb));
errwr_log();
debwr_log();
}
}
close(fd);
return;
}
2). log.h
#ifndef _LOG_H
#define _LOG_H
#include
#include
#include
#include
#include
#include
#include
void
#endif
3). main.c
#include "log.h"
int main(void)
{
open_log("log.t");
return 0;
}
6.其中log.c涉及linux下的常用文件操作文件,内容是简单模拟日志。