iMX6ULL学习(二)

本文深入探讨了Linux开发中的Makefile规则,包括通配符、PHONY假想目标、即时与延迟变量、make函数的使用。同时介绍了字符编码格式转换,如GB2312到UTF-8的转换方法。还涵盖了交叉编译时的常见问题解决,如头文件和库文件问题,以及如何处理运行时找不到动态链接库的情况。此外,文章讲解了TCP和UDP的socket通信流程,并简单提及了多线程编程和TTY设备的相关知识。
摘要由CSDN通过智能技术生成

Makefile机制规则

目标文件 : 依赖文件1 依赖文件2 …
[TAB]命令

当目标文件不存在或某个依赖文件比目标文件时则执行指令。

(一)、通配符

$@ 目标文件
$^ 所有的依赖文件
$< 第一个依赖文件

(二)、PHONY假想目标

#自动检测依赖文件a.o b.o c.o日期是否比目标文件test更新,若是则执行指令编译
test : a.o b.o c.o
        gcc -o test $^
        
#采用通配符%代表编译所有.c依赖文件并生成目标文件
%.o  :%.c
        gcc -c -o $@ $<
        
#用于make clean,清空指定文件
clean: 
        rm *.o test

#定义clean为假想目标(不会判断名为clean的文件是否存在),防止目录下有名为“clean”的文件时导致指令执行错误
.PHONY: clean

(三)、即时变量和延迟变量

  • 即时变量:A := xxx #A的值在定义时即刻被确定
  • 延迟变量:B = xxx #B的值在使用时才被确定
  • 延迟变量:C ?= xxx #如果C第一次被定义则这句生效,否则忽略这句
  • 附加数据 A+=xxx #它是即时/延迟变量取决于前面的定义

(四)、make函数

参考文档地址:http://www.gnu.org/software/make/manual/make.html

$(foreach VAR,LIST,TEXT)

功能:取出list中每个元素,赋值给var变量,然后按照text指定格式输出。
e.g.

objs := a b c
output = $(foreach f, $(objs), $(f).o) #output为a.o b.o c.o
$(filter-out PATTERN…,TEXT)

功能:从text中取值,把符合格式pattern的内容,过滤出来。
e.g.

obj := a b c/
dir := $(filter %/, $(obj))#dir为c/
$(filter-out pattern…, $(var))

功能:从text中取值,把不符合格式pattern的内容,过滤出来。
e.g.

obj := a b c/
dir := $(filter %/, $(obj))#dir为a b
$(wildcard PATTERN)

功能:把符合规则pattern且存在的文件列出来。
e.g.

src_files := $(wildcard *.c)#列出当前目录下所有.c文件
$(patsubst PATTERN,REPLACEMENT,TEXT)

功能:从text中取值,把满足规则pattern的内容转换成replacement格式并输出。(pattern substitution)
e.g.

objc := a.c b.c c.o
files = $(patsubst %.c, %.o, $(objc))#files为a.o b.o c.o

(五)、生成依赖文件

在编译时通过gcc添加附加选项-MD -MF实现(前者代表覆写同名文件,后者代表生成依赖文件.d)。
gcc -c -o xx.o xx.c -MD -MF xx.d
输出文件内容如下

xx.o: xx.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/long-double.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h \
 /usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
 /usr/include/x86_64-linux-gnu/bits/types/FILE.h \
 /usr/include/x86_64-linux-gnu/bits/libio.h \
 /usr/include/x86_64-linux-gnu/bits/_G_config.h \
 /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h

e.g.

objs = a.o b.o c.o
#下面这两句是为了查找实际存在的依赖存放在dep_files
dep_files := $(patsubst %, .%.d, $(objs))
dep_files := $(wildcard $(dep_files))
CFLAGS = -Werror -Iinclude
test: $(objs)
        gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o : %.c
        gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d
clean:
        rm *.o test
distclean:
        rm $(dep_files)
.PHONY: clean

字符编码格式转换

GB2312->UTF-8

gcc -finput-charset=GB2312 -fexec-charset=UTF-8 -o test_charset_ansi test_charset_ansi.c

UTF-8->GB2312

gcc -finput-charset=UTF-8 -fexec-charset=GB2312 -o test_charset_utf8 test_charset_utf8.c

交叉编译时的万能指令

./configure --host=arm-buildroot-linux-gnueabihf --prefix=$PWD/tmp
make make install

常用问题解决方法

头文件问题

描述:#include <xxx.h>查找不到头文件。
方法:使用下列指令确认系统目录LIBRARY_PATH(交叉编译时某个include目录),确定目录下是否有该文件或在编译时使用-I dir指定目录。
echo 'main(){}' | arm-buildroot-linux-gnueabihf-gcc -E -v -

库文件问题

描述:undefined reference to ‘xxx’,xxx函数未定义。
方法:写出这个函数或使用库函数,链接时使用-lxxx添加libxxx.so文件

运行时找不到动态链接库

描述:error while loading shared libraries: libxxx.so:
cannot open shared object file: No such file or directory
方法:查看系统目录(/lib或/usr/lib)是否包含该文件;通过命令指定路径export LD_LIBRARY_PATH=/xxx_dir; ./testLD_LIBRARY_PATH=/xxx_dir ./test

socket通信(TCP方式)

服务端

设计流程:socket() -> bind() -> listen() -> accept() -> recv()/recvfrom() -> send()/sendto()

#include <sys/socket.h>//用于socket常用函数
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>//用于函数htons
#include <unistd.h>
#include <signal.h>//信号处理,用于父进程解决僵尸子进程

#define SERVER_PORT 1997//服务端端口
#define BACKLOG     10//最大连接数

/*
 * int socket(int domain, int type, int protocol);
 * int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 * int listen(int sockfd, int backlog);
 * int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
 * ssize_t send(int sockfd, const void *buf, size_t len, int flags);
 * ssize_t recv(int sockfd, void *buf, size_t len, int flags);
 * int close(int fd);
 */
int main(int argc, char **argv){
   
    int iSocketServer;//服务端socket
    int iSocketClient;//客户端socket
    int iErr;//错误码
    int iRecvLen;//接收数据长度
    int iAddrLen;//地址长度
    unsigned char recv_buff[1024];//接收数据缓冲区
    struct sockaddr_in tServerSocketAddr;//服务端socket地址
    struct sockaddr_in tClientSocketAddr;//客户端socket地址
    signal(SIGCHLD,SIG_IGN);//防止产生僵尸进程
    iSocketServer = socket(AF_INET, SOCK_STREAM, 0);//创建socket
    if(-1 == iSocketServer){
   
        printf("create socket err\n");
        return -1;
    }
    tServerSocketAddr.sin_family      = AF_INET;//地址族ipv4
    tServerSocketAddr.sin_port        = htons(SERVER_PORT);//将端口转换成无符号短整型
    tServerSocketAddr.sin_addr.s_addr = INADDR_ANY;//任何地址都可通过端口连接服务器
    memset(tServerSocketAddr.sin_zero, 0, 8);//清零reserve区域
    iErr = bind(iSocketServer, (const struct sockaddr *)&tServerSocketAddr, sizeof(struct sockaddr));//绑定服务端的socket和地址
    if(-1 == iErr){
   
        printf("bind socket err\n");
        return -1;
    }
    iErr = listen(iSocketServer, BACKLOG);//监听该服务器socket,最大连接数为BACKLOG
    if(-1 ==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值