04linux应用入门

目录

4.1交叉编译hello

4.2GCC

4.2.1GCC编译过程

4.2.2gcc编译选项

Makefile

Makefile规则

Makefile语法

通配符 %.o

假想目标

变量

函数

实例

文件

open

write

read


4.1交叉编译hello

#include <stdio.h>


/* 执行命令: ./hello weidongshan 
 * argc = 2
 * argv[0] = ./hello
 * argv[1] = weidongshan
 */

int main(int argc, char **argv)
{
	if (argc >= 2)
		printf("Hello, %s!\n", argv[1]);
	else
		printf("Hello, world!\n");
	return 0;
}
//argc是参数个数,hello argv[0]
//./hello weidongshan aa
//hello weidongshan
//./hello "weidongshan aa"
//./hello weidongshan aa
arm-buildroot-linux-gnueabinf-gcc -o hello hello.c

stdio.h 头文件在系统目录(工具链)和指定目录

printf 函数在库中,也分系统目录和指定目录

···user 1.app 2.lib.c  printf

···3.kernel fs/driver open read

···硬件

4.2GCC

4.2.1GCC编译过程

预处理 ,查找头文件,展开宏---.i, ---编译--- 汇编语言.s ---汇编--- 机器语言.o--- 链接,多个文件组装在一起

语法错误在编译中发现

4.2.2gcc编译选项

gcc -o -c main.o mian.c
gcc -o -c sub.o sub.c
gcc -o test main.o sub.o
//先预处理,编译汇编,但是不链接

<stdio.h>是去工具链指定的路径查找

" sub.h"是在当前目录下查找,改成<sub.h>是 gcc -c -o main.c  -I ./,指定头文件目录,或者加入到工具链的路径

静态库,找的到库位置

gcc -c -o main.o  main.c 
gcc -c -o sub.o   sub.c 
ar  crs  libsub.a  sub.o  sub2.o  sub3.o(可以使用多个.o生成静态库) 
gcc  -o  test  main.o  libsub.a  (如果.a不在当前目录下,需要指定它的绝对或相对路径) 

动态库,找不到

gcc -c -o main.o  main.c 
gcc -c -o sub.o   sub.c 
gcc -shared  -o libsub.so  sub.o  sub2.o  sub3.o(可以使用多个.o生成动态库) 
gcc -o test main.o  -lsub  -L /libsub.so/所在目录/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
./test 

静态库的在静态阶段链接到了程序中,动态库在程序运行的时候系统动态加载到内存中供程序调用

库 指定的lib目录, 或者-L 

运行时 so 指定lib路径,或者LD_LIBRARY_PATH

Makefile

Makefile规则

只对修改的文件相关的重编译

比较时间 gcc -o test a.o b.o 如果test时间早于a.o b.o ,说明被修改

1.依赖文件比目标文件新 2.目标文件不存在 执行命令

//依赖文件:目标文件
//TAB命令
makefile
test:a.o b.o 
    gcc -o test a.o b.o
a.o:a.c 
    gcc -o -c a.o a.c
b.o:b.c 
    gcc -o -c b.o b.c
//makefile文件包括这些内容,执行make命令就可以了

Makefile语法

通配符 %.o
test:a.o b.o c.o
    gcc -o test $^//所有的依赖
%.o:%.c 
    gcc -o -c $@目标文件 $<第一个依赖文件
假想目标

make [目标] 若无目标,默认第一个目标

test:a.o b.o c.o
    gcc -o test $^//所有的依赖
%.o:%.c 
    gcc -o -c $@目标文件 $<第一个依赖文件
clean:
    rm *.o test
.PHONY: clean

若文件中有clean同名文件,则不能执行make命令

所以采用假想目标 .PHONY:clean,就不会判断clean是否存在

变量

简单变量(即时变量)

     A:=XXX //A的值立刻决定

     B=XXX  //B的值到使用时才决定

      :=    //即时变量

      =    //延时变量

     ?=   //延时变量,如果是第一次定义才起效,如果在前面该变量已定义则忽略这句话

     +=   //附加:他是即时变量还是延时变量取决于前面的定义

A:=$(C)
B=$(C)
C=abc
D=100ASK
D?=SU

all:
    @echo A=$(A)
    @echo B=$(B)
    @echo D=$(D)
C+=123
//A=   
//B=abc 123
//D=100ASK
函数

$(foreach var,list,text)对list 中的每一个元素,取出来赋给var,然后把var改为text所描述 的形式。

A=a b c
B=$(foreach f,$(A),.$(f).o)

all:
    @echo$(B)

//a.o b.o c.o

$(filter pattern...,text)在text中取出符合pattern格式的值

$(filter-out pattern...,text)在text中取出不符合pattern格式的值

A= a b c d/
B=$(filter %/,$(A))
C=$(filter-out %/,$(A))

all:
    @echo$(B)
    @echo$(C)
//d/
//a b c

$(wildcard pattern) pattern所列出的文件是否存在,把存在的文件都列出来。

$(wildcard *.c)

$(patsubst pattern,replacement,$(var)从列表中取出每一个值如符合pattern则替换成replacement

file=a.c b.c c.c abc
file1=$(patsubat %.c ,%.d,$(file))

all:
    @echo$(file1)
//a.d b.d c.d
实例

c.c需要依赖头文件c.h

gcc -M c.c打印出依赖
gcc -M -MF c.d c.c//把依赖写入c.d
gcc -c -c c.o c.c -MD -MF c.d//编译c.c,把依赖写入c.d
objs=a.c b.c c.c
dep_files:=$(patsubst %,.%.d,$(objs))
dep_files:=$(wildcard$(dep_files)

CFLAGS=-Werror -Iinclude//把警告都当成错误,把头文件放到include

test:a.o b.o c.o
    gcc -o test $^
    @echo dep_files=$(dep_files)//a..d b.o.d c.o.d都生成.d文件,就不用单独把从c.d写个命令

ifneq($(dep_files),)
include$(dep_files)
endif

%.o:%.c 
    gcc $(CFLASS) -o -c $@ $< -MD -MF .$@.d
clean:
    rm *.o test
disclean:
    rm$(dep_files)
.PHONY: clean

文件

标准IO

系统调用IO

比如这个fread第一次进入系统内核,存入buf,之后都不进入内核,直接从buf里读数据

open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include<unistd.h>
/*./open 1.txt
 argc=2
 argv[0]=./open
 argv[1]=1.txt
*/
       int main (int argc,char **argv)
       {
        int fd;
        if(argc!=2){
            printf("Usage: %s <file>\n",argv[0]);
            return -1;
        }
        fd=open(argv[1],O_RDWR);
        if(fd<0){
            printf("can not open file :%s\n",argv[1]);
            printf("errro is :%d\n",errno);
            printf("err:%s\n",strerror(errno));//把错误类型打印出来
            perror("open");

        }
        while(1){
            sleep(10);
        }
        close(fd);
        return 0;
        }

0号标准输入,1标准输出,3 错误信息,fd=3要打开的文件 ./open open.c &

open的权限RDWR 文件权限只读无法打开

fd=open(argv[1],O_RDWR|O_CREAT|O_TRUNC);
mode&~umask
umask002 book

对于已经存在的文件,无法修改文件,重新创建的文件可以修改文件

write

./write 1.txt abc 2024 913
 for(i=2;i<argc;i++){
        int len=write(fd,argv[i],strlen(argv[i]));
        if(len!=strlen(argv[i]))
        {
            perror("write");
            break;
        }
        write(fd,"\r\n",2);
       }

read
  while (1)
       {
       int len=read(fd,buf,sizeof(buf));
       if(len<0){
        perror("read");
        close(fd);
       return -1;
       }else if(len==0){
        break;
       }
       else{
        buf[len]='\0';
        printf("%s",buf);
       }
       
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include<unistd.h>
/*逐行处理
readline
process_line
写入新文件
./process score.csv result.csv
 argc=3
 argv[0]=./process
 argv[1]=score.csv
 argv[2]=result.csv

*/
//返回值n一行数据个数,-1表示读到尾部或者出错
static int read_line(int fd,unsigned char *buf){
    //循环的读入字符,读到0X0d 0x0a
    unsigned char c;
    int len;
    int i=0;
    int err=0;
    while (1)
    {
       len=read(fd,&c,1);
       if(len<=0){
         err=-1;
         break;
       }else{
         if(c!='\n'&&c!='\r'){
            buf[i]=c;
            i++;
         }else{
            //碰到回车换行
            err=0;
            break;
        }
       }
    }
    buf[i]='\0';
    if(err&&(i==0)){
        //读到了尾部,并且一个数据都没有读进来
          return -1;
    }else{
    //读到尾部了,之前读到了数据
        return i;
     }
    }

int process_data(unsigned char *data_buf,unsigned char *result_buf){
    //第一行不做处理
    //之后的处理数据,求和评价
    char name[100];
    int score[3];
    int sum;
    char *levels[]={"A+","A","B"};
    int level;
    if(data_buf[0]==0xef)//UTF-8文件,前3个字符是0XEF 0XBB 0XBF
    {
        strcpy(result_buf,data_buf);
    }else{
        sscanf(data_buf,"%[^,],%d,%d,%d,",name,&score[0],&score[1],&score[2]);
        //printf("result:%s,%d,%d,%d\n\r",name,score[0],score[1],score[2]);
        sum=score[0]+score[1]+score[2];
        if(sum>=170)
        level=0;
        else if(sum>240)
        level=1;
        else
        level=2;

        sprintf(result_buf,"%s,%d,%d,%d,%d,%s",name,score[0],score[1],score[2],sum,levels[level]);
       // printf("result:%s",result_buf);
    }
}



int main (int argc,char **argv)
       {
        int fd_data,fd_result;
        int i;
        unsigned char data_buf[1000];
        unsigned char result_buf[1000];


        if(argc!=3){
            printf("Usage: %s <score><result> ...\n",argv[0]);
            return -1;
        }

        fd_data=open(argv[1],O_RDWR|O_CREAT,0664);
        if(fd_data<0){
            printf("can not open file :%s\n",argv[1]);
            perror("open");
            return -1;
        }else{
            printf("data fd=%d\n",fd_data);
        }

        fd_result=open(argv[2],O_RDWR|O_CREAT,0664);
        if(fd_result<0){
            printf("can not create file :%s\n",argv[2]);
            perror("create");
            return -1;
        }else{
            printf("result fd=%d\n",fd_result);
        }

        while (1)
        {
            //从数据文件读取一行
            int len =read_line(fd_data,data_buf);
            if(len==-1){
                break;
            }
            
            //处理数据
            if(len!=0){
              process_data(data_buf,result_buf);
              write(fd_result,result_buf,strlen(result_buf));
               write(fd_result,"\r\n",2);
            }
            //写入结果文件
           /// write_data(fd_result,result_buf);
        }
        
     close(fd_result);
     close(fd_data);
        return 0;
       }

系统调用


long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
	struct open_flags op;
	int fd = build_open_flags(flags, mode, &op);
	struct filename *tmp;

	if (fd)
		return fd;

	tmp = getname(filename);
	if (IS_ERR(tmp))
		return PTR_ERR(tmp);

	fd = get_unused_fd_flags(flags);//未使用的句柄
	if (fd >= 0) {
		struct file *f = do_filp_open(dfd, tmp, &op);//打开文件得到file结构体
		if (IS_ERR(f)) {
			put_unused_fd(fd);
			fd = PTR_ERR(f);
		} else {
			fsnotify_open(f);
			fd_install(fd, f);当前进程下记录下来
		}
	}
	putname(tmp);
	return fd;
}

file-> f_pos

void fd_install(unsigned int fd, struct file *file)
{
	__fd_install(current->files, fd, file);
}

current->task struct->files->fdtable fdt->fd数组->file->f_pos

int fd=open(argv[1],O_RDONLY);
int fd2=open(argv[1],O_RDONLY);
int fd3=dup(fd);

fd=3;
fd2=4;
fd3=5;
但是fd3和fd对应同一个file结构体,当read(fd,buf,1)f_pos从0-1
read(fd3,buf,1)会从1-2

dup2

1文件重定向到3文件对应的1.txt,hello world输入到1.txt

字符串

0.........x_wide-1

.......

0........x_wide-1 y行

0....x

(y*x_wide+x)*BPP/8,bpp是一个像素用多少位表示,除以8是字节数

(x,y)像素起始地址=fb_base+(xres*bpp/8)*y + x*bpp/8 
 line_width  = var.xres * var.bits_per_pixel / 8; 
 pixel_width = var.bits_per_pixel / 8; 
screen_size = var.xres * var.yres * var.bits_per_pixel / 8; 
unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width;
API
open
ioctl获取分辨率和bpp
mmap framebuffer是驱动管理,得映射到应用空间

字符

ANSI编码,选择不同的字符集对应不一样

unicode,一对一,包含ascii码,最大字节0xFFFFFF

网络通信

服务器被动的响应请求

客户端 主动发起请求

TCP可靠的 UDP不可靠

服务器根据源端口来区分同一个IP下的两个连接                  客户端

fd=socket()                                                                           fd=socket

bind(自己的ip,端口,)把fd和IP端口绑定起来                      

listen(启动监测数据

accept(接受一条连接                                                            connect建立连接                                   

send recv

串口

UART

UART硬件

用途:打印信息,外接各种模块

使用串口

1.波特率 2.格式:数据位,停止位,校验位,流控

怎么发送A,0X41 0b01000001

双方约定波特率,每一位占据的时间,假设1s

数据+校验位+停止位

115200.8n1

波特率115200,八位数据位,一位停止位

开始位,数据位,停止位 10位

每一位需要1/115200s,每秒传输 115200/10=11520byte

TTY设备节点的区别

/dev/ttyS0串口 /dev/ttySAC0 /dev/tty当前终端 /dev/tty0前台终端 /dev/tty1 /dev/console 

TTY设备驱动程序,输入输出设备 terminal终端 Console 控制器 UART串口

TTY驱动程序的框架

在Linux系统中,操作设备的统一接口,open,ioctl,read,write

UART在ioctl之上封装了很多函数,主要是设置行规程

*open

*设置行规程(结构体),比如波特率,数据位,停止位,校验位,RAW模式(APP应用处理数据等,一有数据就返回

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>

/* 设置set_opt(fd,115200,8,'N',1) */
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;
	//清空
	if ( tcgetattr( fd,&oldtio) != 0) { 
		perror("SetupSerial 1");
		return -1;
	}
	
	bzero( &newtio, sizeof( newtio ) );
	newtio.c_cflag |= CLOCAL | CREAD; 
	newtio.c_cflag &= ~CSIZE; 
   
	newtio.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
	newtio.c_oflag  &= ~OPOST;   /*Output*/

	switch( nBits )
	{
	case 7:
		newtio.c_cflag |= CS7;
	break;
	case 8:
		newtio.c_cflag |= CS8;
	break;
	}

	switch( nEvent )
	{
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
	break;
	case 'E': 
		newtio.c_iflag |= (INPCK | ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
	break;
	case 'N': 
		newtio.c_cflag &= ~PARENB;
	break;
	}

	switch( nSpeed )
	{
	case 2400:
		cfsetispeed(&newtio, B2400);
		cfsetospeed(&newtio, B2400);
	break;
	case 4800:
		cfsetispeed(&newtio, B4800);
		cfsetospeed(&newtio, B4800);
	break;
	case 9600:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
	break;
	case 115200:
		cfsetispeed(&newtio, B115200);
		cfsetospeed(&newtio, B115200);
	break;
	default:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
	break;
	}
	
	if( nStop == 1 )
		newtio.c_cflag &= ~CSTOPB;
	else if ( nStop == 2 )
		newtio.c_cflag |= CSTOPB;
	
	newtio.c_cc[VMIN]  = 1;  /* 读数据时的最小字节数: 没读到这些数据我就不返回! */
	newtio.c_cc[VTIME] = 0; /* 等待第1个数据的时间: 
	                         * 比如VMIN设为10表示至少读到10个数据才返回,
	                         * 但是没有数据总不能一直等吧? 可以设置VTIME(单位是10秒)
	                         * 假设VTIME=1,表示: 
	                         *    10秒内一个数据都没有的话就返回
	                         *    如果10秒内至少读到了1个字节,那就继续等待,完全读到VMIN个数据再返回
	                         */

	tcflush(fd,TCIFLUSH);
	
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
	//printf("set done!\n");
	return 0;
}

int open_port(char *com)
{
	int fd;
	//fd = open(com, O_RDWR|O_NOCTTY|O_NDELAY);
	fd = open(com, O_RDWR|O_NOCTTY);
    if (-1 == fd){
		return(-1);
    }
	
	  if(fcntl(fd, F_SETFL, 0)<0) /* 设置串口为阻塞状态*/
	  {
			printf("fcntl failed!\n");
			return -1;
	  }
  
	  return fd;
}


/*
 * ./serial_send_recv <dev>
 */
int main(int argc, char **argv)
{
	int fd;
	int iRet;
	char c;

	/* 1. open */

	/* 2. setup 
	 * 115200,8N1
	 * RAW mode
	 * return data immediately
	 */

	/* 3. write and read */
	
	if (argc != 2)
	{
		printf("Usage: \n");
		printf("%s </dev/ttySAC1 or other>\n", argv[0]);
		return -1;
	}

	fd = open_port(argv[1]);
	if (fd < 0)
	{
		printf("open %s err!\n", argv[1]);
		return -1;
	}

	iRet = set_opt(fd, 115200, 8, 'N', 1);
	if (iRet)
	{
		printf("set port err!\n");
		return -1;
	}

	printf("Enter a char: ");
	while (1)
	{
		scanf("%c", &c);
		iRet = write(fd, &c, 1);
		iRet = read(fd, &c, 1);
		if (iRet == 1)
			printf("get: %02x %c\n", c, c);
		else
			printf("can not get data\n");
	}

	return 0;
}

*read/write

I2C

写操作

start操作-设备地址7bit -方向0表示写1表示读-回应-数据8bit-回应-数据8bit-回应-P结束 

SDA 从高到低 -开始          从低到高-结束    切换数据  保持数据稳定  从设备存在拉低信号,回应

SCL  保持高电平              保持高电平           低电平时   高电平

主设备和从设备都驱动时,采用三极管,保证电路安全

对SDA 前8CLK主设备,9CLK从设备,ACK=0

对SCL  前9CLK主设备,10从设备,SCL=0从设备处理一下别的事情


SMBus协议,系统管理总线

SMBus是I2C的一个子集

重要结构体

I2C_adapter .nr第几条I2C总线 .xfer传输函数

i2ctools

访问i2c_dev.c i2c_gpio.c 访问i2c——devices

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值