LINUX基础
Linux基本命令
Linux下皆文件
查询man手册 --> Ubuntu系统提供的官方说明书
man man #使用man命令来查看man
man -f #查看函数/命令在哪本手册中
man -f ls #查询ls在哪个手册
man 1 open #查询open命令
man 2 open #查询open函数
sudo -s #切换超级用户命令
exit #退出超级用户
even:当前用户名
@:机器标志——将用户名和主机名隔开
ubuntu:主机名
~[……]:当前工作路径
用户标识符:
$ 普通用户标识符
# 超级用户标识符
=============================================
ls 列出当前用户名
ls -l #以详细信息列出当前目录的内容
从左到右依次
文件类型
- 普通文件
d 目录文件(文件夹)
l 链接文件 --> 快捷方式
p 管道文件 可以作为进程间通信的媒体
b 块设备文件(驱动文件用的比较多)
s socket(网络套接字)
三个用户的文件权限
- 0
r 可读
w 可写
x 可执行
rwx拥有权值
可读可写可执行
三个rwx表示的权限归属:
文件拥有者、同组用户、其他用户
文件链接数
普通文件:链接数表示该文件的快捷方式有几个
目录文件:链接数表示该目录中有几个文件
文件拥有者
文件所属小组
文件大小
最后修改时间
文件名
ls -a #列出当前目录的所有内容
.xxxx 都是隐藏文件
. 当前路径
. . 上一级路径
~ 当前用户的家目录的缩写 --> /home/even/
/ 根目录:当前系统的起源路径(系统中所有的文件都能从这里开始找到)
cd #切换工作路径
cd .. #切换到上一级路径
rm #删除文件
rm [filename] #永久删除文件
rm -rf [filename] #删除目录下所有文件
#如果需要删除/创建的文件在用户的路径以外,需要使用sudo
touch [filename] #创建普通文件
mkdir [filename] #创建目录文件
chmod #修改权限
chmod u+x [filename] #文件拥有者权限增加x权限(增加可执行权限)
chmod 666 [filename] #通过权值同时修改三个用户的权限
#6文件拥有者可读可写不可执行
#6同组用户可读可写不可执行
#6其他用户可读可写不可执行
cp #复制文件
cp [filename1] [filename2]
#filename2如果是已经存在的目录文件,将filename1复制到filename2目录下
#filename2如果是原来不存在的文件名,将filename1复制一个新文件filename2
cat #偷看文件内容
cat [filename]
cat [filename] -n #标出每行的序号
mv #移动文件(剪切)/重命名
mv [filename] [一个已经存在的目录文件] #移动文件
mv [filename] [一个不存在的文件名] #重命名
pwd #打印当前的工作路径
clear #清屏
#快捷键:Ctrl+l
history #查看历史命令
grep #在文件中搜索某个单词
grep [单词] [文件] [序号]
grep as 985 #使用 grep 在文件 985 中搜索包含 as 的内容
grep as 985 -n #输出结果包含行号
==============================================================================
文件编辑器
gedit 必须是有界面的操作系统
vi/vim 没有图形界面的操作系统也可用
一般情况下使用 VIM 打开文件都处于命令模式下
在命令模式下按下键盘 I 键可以进入编辑模式
在编辑模式下按下 Esc 可以退出编辑模式
在命令模式下输入 冒号(:) 可以进入尾行模式
在尾行模式下:
:q! 可以强制退出而不保存
:w 保存文件
:q 退出
:wq 保存退出
VIM 的三种模式:
命令模式
编辑模式
尾行模式
sublime
gedit [filename] #以gedit打开
vim [filename] #以vim打开
subl [filename] #以sublime打开
find #查找
find -name "*.bmp" #使用find命令查找当前路径,以名字来查找
# * 通配符(通用匹配符号)
文件IO
sudo #获取root管理员权限
rm #remove,即删除
-rf #表示递归删除,即删除所有的子目录,f表示不需要再进行确认
/ #home目录
* #所有文件
open ( 打开文件 )
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
定义函数:
int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);
参数分析:
pathname --> 需要打开的文件的 路径 + 名字
flags --> 所能使用的旗标
O_RDONLY 以只读方式打开文件
O_WRONLY 以只写方式打开文件
O_RDWR 以可读写方式打开文件
上述三种旗标是互斥的,,也就是不可同时使用,但可与下列的旗标利用:
OR(|)运算符组合.
返回值:
成功 返回新的文件描述符 (return the new file descriptor)
int --> 整型 --> 数字 --> 编号 (只能在当前进程中使用)
失败 返回 -1 错误号码会被设置
write ( 将数据写入已打开的文件内 )
头文件:
#include <unistd.h>
定义函数:
ssize_t write (int fd, const void * buf, size_t count);
参数分析:
fd --> 需要写入的文件的文件描述符
buf --> 需要写入的数据所在的地址
count --> 需要写入的字节数
返回值:
成功 实际写入的字节数
失败 则返回-1, 错误代码存入 errno 中
close ( 关闭文件 )
头文件:
#include <unistd.h>
定义函数:
int close(int fd);
参数分析:
fd --> 需要关闭的文件的文件描述符
返回值:
若文件顺利关闭则返回 0,
发生错误时返回-1.
应用代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{
if(argc != 3){
printf("请输入正确的参数个数!\n");
return -1;
}
int fd_text1 = open(argv[1], O_RDWR | O_CREAT, 0666);
int fd_text2 = open(argv[2], O_RDWR | O_CREAT, 0666);
if(-1 == fd_text1 || -1 == fd_text2){
perror("open error");
return -1;
}
char temp;
while(1){
int res1 = read(fd_text1, &temp, 1);
if(res1 == 1){
int res2 = write(fd_text2, &temp, res1);
if(res2 == -1){
perror("write error");
return -1;
}
}else if(res1 == 0){
printf("success\n");
break;
}else if(res1 == -1){
perror("read error");
return -1;
}
}
close(fd_text1); close(fd_text2);
return 0;
}
LCD模拟显示
在编写代码之前,先安装LCD模拟显示器软件
要让颜色在LCD显示屏上显示出来,就好比抄作业,我们首先要打开自己的作业本和同学的作业本(open()),然后读取(看)同学作业本上的内容(read()),最后写到自己的作业本上(write()),抄完后合上(关闭)自己和同学的作业本(close())。
但是,人的记忆是有限的,系统能读取的长度也是有限的,我们不能一次性记住作业本上的所有内容,所以我们要多次read。
内存映射
在进行显示的时候发现,在第一次使用显示屏显示的时候,设定的颜色能完整正确地覆盖整个800*480,但在对存储颜色的十六进制码的变量进行更改再编译执行之后,显示器依旧显示原来的颜色,并没有刷新。同时我们发现,显示器显示的速度很慢,是从上往下刷出来的。
在这里我们用到内存映射,用于提高执行效率,无需反复读写。使用 mmap() 函数在文件和内存之间建立一个关系,mmap函数的返回值是一个内存地址,指向我们要操作的内存。我们将这个地址强制转换成整型地址,以便使用。
显示颜色(无刷新):
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{
//打开LCD设备文件
int fd_lcd = open("/dev/ubuntu_lcd", O_RDWR);
if(fd_lcd == -1){
perror("open LCD error ");
return -1;
}
ftruncate(fd_lcd, 0);
lseek(fd_lcd, 0, SEEK_SET);
//写入RGB颜色
int x, y;
int yellow = 0xFFFF00;
int black = 0x000000;
//循环遍历
int n = 480;
while(n){
if(n == 480 || n == 1){
for (x = 0; x < 800; x++){
write(fd_lcd, &yellow, 4);
}
}else{
write(fd_lcd, &yellow, 4);
for(x = 0; x < 798; x++){
write(fd_lcd, &black, 4);
}
write(fd_lcd, &yellow, 4);
}
n--;
}
//关闭文件
close(fd_lcd);
return 0;
}
显示图片(在内存操作,有刷新):
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define W 800
#define H 480
#define LCD_PATH "/dev/ubuntu_lcd"
#define LCD_SIZE W*H*4 //每个像素点4个字节
#define BMP_PATH "1.bmp"
#define BMP_SIZE W*H*3 //每个像素点3个字节
int main(int argc, char const *argv[]){
//打开lcd显示器
int fd_lcd = open(LCD_PATH, O_RDWR);
if(fd_lcd == -1){
perror("open lcd error");
return -1;
}
//内存映射
int * p_lcd = (int *)mmap(NULL, LCD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd_lcd, 0);
if(p_lcd == MAP_FAILED){
perror("mmap error");
return -1;
}
//打开图片
int fd_bmp = open(BMP_PATH, O_RDONLY);
if(fd_bmp == -1){
perror("open bmp error\n");
return -1;
}
//读取图片信息
lseek(fd_bmp, 54, SEEK_SET);
char buf_bmp[BMP_SIZE];
int ret = read(fd_bmp, buf_bmp, BMP_SIZE);
printf("Read: %d\n", ret);
//24位bmp图片数转换32位
int lcd_buf[H][W];
int x, y;
for(y = 0; y < H; y++){
for(x = 0; x < W; x++){
lcd_buf[y][x] = (buf_bmp[(x+y*800)*3 + 0] & 0xFF) << 0 |
(buf_bmp[(x+y*800)*3 + 1] & 0xFF) << 8 |
(buf_bmp[(x+y*800)*3 + 2] & 0xFF) << 16;
}
}
//显示图像
int t = 0;
for (y = H-1; y > 0; y--){
for(x = 0; x < W; x++){
*(p_lcd+x+t*800) = lcd_buf[y][x];
}
t++;
}
//资源回收
close(fd_lcd);
close(fd_bmp);
munmap(p_lcd,LCD_SIZE);
return 0;
}
其中:
因为读取图片和显示像素的时候坐标原点不同,读取图片从左下角开始,显示图片从左上角开始,故需要进行优化,两种方式中,下方的优化方式更好。
int lcd_buf[H][W];
int x, y;
for(y = 0; y < H; y++){
for(x = 0; x < W; x++){
lcd_buf[y][x] = (buf_bmp[(x+y*800)*3 + 0] & 0xFF) << 0 |
(buf_bmp[(x+y*800)*3 + 1] & 0xFF) << 8 |
(buf_bmp[(x+y*800)*3 + 2] & 0xFF) << 16;
}
}
//显示图像
int t = 0;
for (y = H-1; y > 0; y--){
for(x = 0; x < W; x++){
*(p_lcd+x+t*800) = lcd_buf[y][x];
}
t++;
}
======================================================================
int lcd_buf[H][W];
int x, y;
for(y = 0; y < H; y++){
for(x = 0; x < W; x++){
lcd_buf[479-y][x] = (buf_bmp[(x+y*800)*3 + 0] & 0xFF) << 0 |
(buf_bmp[(x+y*800)*3 + 1] & 0xFF) << 8 |
(buf_bmp[(x+y*800)*3 + 2] & 0xFF) << 16;
}
}
//显示图像
for (y = 0; y < 480; y++){
for(x = 0; x < W; x++){
*(p_lcd+x+y*800) = lcd_buf[y][x];
}
}