触屏实现
- 文件操作:
open
函数:用于打开文件或设备,返回文件描述符。在这里,它用于打开触摸屏设备文件/dev/input/event0
。read
函数:从文件或设备中读取数据。这里,它用于读取触摸事件数据到struct input_event
结构体中。close
函数:关闭打开的文件或设备。
- 结构体与内存操作:
struct input_event
结构体:这是Linux输入子系统定义的一个结构体,用于表示输入事件。它包含事件类型(type
)、事件代码(code
)和事件值(value
)。memset
函数:用于将内存块的内容设置为指定的值,这里用于清零struct input_event
结构体,确保在读取新事件前结构体是干净的。
- 条件判断与循环:
if
语句:用于条件判断,这里用于检查事件类型、事件代码和事件值,以确定触摸行为(按下或抬起)和触摸坐标。while
循环:用于持续监听触摸事件,直到程序被外部方式终止。
- 输入事件处理:
- 输入事件类型(
event.type
):EV_KEY
表示按键事件,EV_ABS
表示绝对坐标事件。 - 事件代码(
event.code
):对于EV_KEY
类型,BTN_TOUCH
表示触摸行为;对于EV_ABS
类型,ABS_X
和ABS_Y
分别表示X轴和Y轴的绝对坐标。 - 事件值(
event.value
):对于EV_KEY
类型,值为1表示按下,0表示抬起;对于EV_ABS
类型,值表示坐标的具体数值。
- 输入事件类型(
- 坐标转换:
- 代码中进行了坐标转换,以适应不同触摸屏的分辨率。例如,X坐标被乘以
800/1024
,Y坐标被乘以480/600
,这可能是为了将触摸屏的原生分辨率转换为应用程序或显示设备所需的分辨率。
- 代码中进行了坐标转换,以适应不同触摸屏的分辨率。例如,X坐标被乘以
- 错误处理:
- 使用
perror
函数打印打开文件失败时的错误信息。
- 使用
- Linux输入子系统:
- 这段代码展示了如何在Linux环境下使用输入子系统来读取和处理来自输入设备(如触摸屏)的事件。输入子系统是Linux内核的一部分,提供了一种统一的方式来处理各种输入设备。
- 头文件包含:
#include <stdio.h>
:包含标准输入输出库的头文件,用于printf
和puts
等函数。#include "header.h"
:可能是一个自定义头文件,但在这段代码中没有给出其内容。它可能包含了一些额外的定义或声明。#include <linux/input.h>
:包含Linux输入子系统相关的定义和声明,如struct input_event
结构体和事件类型常量。
#include <stdio.h>
#include "header.h"
#include <linux/input.h>
//触摸屏的设备文件路径
#define DEV_TOUCH "/dev/input/event0"
int main(int argc, char const *argv[])
{
//1.打开文件
int fd = open(DEV_TOUCH, O_RDONLY);
if (fd == -1)
{
perror("open touch failed");
return -1;
}
//2.操作文件
//定义结构体变量
struct input_event event;
//结构体清零操作
memset(&event, 0, sizeof(event));
//循环检测输入设备的状态变化
while (1)
{
//读取输入设备文件数据到结构体中
read(fd, &event, sizeof(event));
/*
type: 区分事件的类型:EV_KEY: 类似按键行为
code: 进一步筛选事件:
BTN_TOUCH :触摸行为
value: 进一步筛选事件
0抬起状态,1按下状态
*/
//检测手指的按下或抬起状态
if (event.type == EV_KEY)
{
if (event.code == BTN_TOUCH)
{
printf("%d\n", event.value);
if (event.value ==1)
puts("手指按下状态!");
else
puts("手指抬起状态!");
}
}
//检测手指触摸的坐标
if (event.type == EV_ABS)
{
if (event.code == ABS_X)
{
//GEC6818有两个批次,黑色地板和蓝色地板;蓝色地板代码不变
//printf("X方向的绝对坐标值是:%d\n", event.value);
//黑色地板的触摸检查范围是1024 600; 可以做如下的处理
printf("X方向的绝对坐标值是:%d\n", event.value * 800 / 1024);
}
else if(event.code == ABS_Y)
{
//printf("Y方向的绝对坐标值是:%d\n", event.value);
//黑色地板的触摸检查范围是1024 600; 可以做如下的处理
printf("X方向的绝对坐标值是:%d\n", event.value * 480 / 600);
}
}
//结构体清零操作
memset(&event, 0, sizeof(event));
}
//3.关闭文件
close(fd);
return 0;
}
ls指令实现
-
文件类型判断:
S_ISLNK(mode)
、S_ISREG(mode)
、S_ISDIR(mode)
、S_ISCHR(mode)
、S_ISBLK(mode)
、S_ISSOCK(mode)
、S_ISFIFO(mode)
:这些宏用于判断文件的类型,如符号链接、普通文件、目录、字符设备文件、块设备文件、套接字和命名管道(FIFO)。mode_t
:这是一个数据类型,用于表示文件的模式(包括类型和权限)。
st_mode 常见取值: (八进制,文件类型主要取决第3字节) S_IFSOCK 0140000 socket 套接字文件 S_IFLNK 0120000 链接文件 S_IFREG 0100000 一般文件 S_IFBLK 0060000 块设备文件 S_IFDIR 0040000 目录 S_IFCHR 0020000 字符设备文件 S_IFIFO 0010000 管道文件 上述的文件类型在POSIX中定义了检查这些类型的宏定义: S_ISLNK (st_mode) 判断是否为链接文件 S_ISREG (st_mode) 是否为一般文件 S_ISDIR (st_mode) 是否为目录 S_ISCHR (st_mode) 是否为字符设备文件 S_ISBLK (st_mode) 是否为块设备文件 S_ISSOCK (st_mode) 是否为socket套接字文件 S_ISFIFO (st_mode) 是否为管道文件
-
文件权限处理:
S_IRWXU
、S_IRUSR
、S_IWUSR
、S_IXUSR
:这些宏分别表示用户(文件所有者)的读、写、执行权限。S_IRWXG
、S_IRGRP
、S_IWGRP
、S_IXGRP
:这些宏分别表示用户组的读、写、执行权限。S_IRWXO
、S_IROTH
、S_IWOTH
、S_IXOTH
:这些宏分别表示其他用户的读、写、执行权限。- 位运算(
&
):用于提取特定的权限位。
S_IRWXU 00700 文件拥有者可读,可写,可执行 S_IRUSR 00400 文件拥有者可读 S_IWUSR 00200 文件拥有者可写 S_IXUSR 00100 文件拥有者可执行 S_IRWXG 00070 组用户可读,可写,可执行 S_IRGRP 00040 组用户可读 S_IWGRP 00020 组用户可写 S_IXGRP 00010 组用户可执行 S_IRWXO 00007 其他组用户可读,可写,可执行 S_IROTH 00004 其他组用户可读 S_IWOTH 00002 其他组用户可写 S_IXOTH 00001 其他组用户可执行
-
字符串操作:
strcat
:用于连接两个字符串。在这里,它用于将权限字符(如"rwx")追加到info
字符串的末尾。- 字符数组(
char *info
):用于存储最终的文件类型和权限信息。
-
用户和组信息获取:
uid_t
、gid_t
:这些数据类型分别用于表示用户ID和组ID。getpwuid
:根据用户ID获取用户信息结构体passwd
。getgrgid
:根据组ID获取组信息结构体group
。struct passwd
、struct group
:这些结构体分别包含用户和组的信息,如用户名、组名、用户ID、组ID等。pw_name
、gr_name
:这些成员分别表示用户名和组名。
struct passwd { char* pw_name; /* user name */ char* pw_passwd; /* user password */ uid_t pw_uid; /* user ID */ gid_t pw_gid; /* group ID */ char* pw_gecos; /* user information */ char* pw_dir; /* home directory */ char* pw_shell; /* shell program */ }; struct group { char* gr_name; /* group name */ char* gr_passwd; /* group password */ gid_t gr_gid; /* group ID */ char** gr_mem; /* group members */ };
-
错误处理:
- 在
getOwnerGroupName
函数中,通过检查getgrgid
的返回值是否为NULL
来处理获取组信息失败的情况。
- 在
-
结构体成员访问:
- 代码通过
pstat->st_mode
、pstat->st_uid
、pstat->st_gid
来访问Stat
结构体(这里假设是struct stat
的别名或类似结构)的成员,这些成员分别表示文件的模式、所有者的用户ID和所有者的组ID。
- 代码通过
-
函数设计和返回值:
- 每个函数都接受一个指向
Stat
结构体的指针和一个字符数组作为参数,用于获取文件信息并填充到字符数组中。 - 函数的返回值用于表示操作的成功或失败(尽管在某些函数中,如
getOwnerPrem
、getgrPrem
和getgrrPrem
,返回值似乎没有被充分利用)。
- 每个函数都接受一个指向
-
打印调试信息:
printf
用于打印文件的模式(以八进制表示)和用户组权限的调试信息。
需要注意的是,代码中有几个潜在的问题和改进点:
getFileType
函数没有返回值,但根据函数名和上下文,它应该返回一个表示文件类型的字符或某种状态码。然而,它实际上是通过修改info
字符串来传达信息的。- 在
getOwnerPrem
、getgrPrem
和getgrrPrem
函数中,虽然计算了权限并更新了info
字符串,但返回值没有被用来表示不同的权限组合情况,这可能导致调用者无法准确知道函数执行的结果。 - 在使用
strcat
之前,应该检查info
字符串是否有足够的空间来容纳追加的内容,以避免缓冲区溢出。 Stat
结构体在代码中没有定义,但根据上下文,它应该是struct stat
的别名或具有相似成员的自定义结构体。在实际使用中,需要确保这个结构体与stat
系统调用的输出兼容。
myls.c
#include "header.h"
// 1.获取文件的类型
int getFileType(Stat *pstat, char *info)
{
// 获取结构体成员的值
mode_t mode = pstat->st_mode;
printf("mode: %o\n", mode);
// 判断文件类型
if (S_ISLNK(mode))
info[0] = 'l';
else if (S_ISREG(mode))
info[0] = '-';
else if (S_ISDIR(mode))
info[0] = 'd';
else if (S_ISCHR(mode))
info[0] = 'c';
else if (S_ISBLK(mode))
info[0] = 'b';
else if (S_ISSOCK(mode))
info[0] = 's';
else if (S_ISFIFO(mode))
info[0] = 'p';
}
int getOwnerPrem(Stat *pstat, char *info)
{
// 获取结构体成员的值
mode_t mode = pstat->st_mode; // 40542
/*
100 000 101 100 010
& 000 000 111 000 000
---------------------------
000 000 101 000 000
0 0 5 0 0
*/
// 判断文件类型
// int perm = mode & 00700; drwx0000000000000000
int perm = mode & S_IRWXU;
if (perm == S_IRWXU)
strcat(info, "rwx");
else if (perm == S_IRUSR)
strcat(info, "r--");
else if (perm == S_IWUSR)
strcat(info, "-w-");
else if (perm == S_IXUSR)
strcat(info, "--x");
else if (perm == (S_IRUSR | S_IWUSR))
strcat(info, "rw-");
else if (perm == (S_IXUSR | S_IWUSR))
strcat(info, "-wx");
else if (perm == (S_IXUSR | S_IRUSR))
strcat(info, "r-x");
else
strcat(info, "---");
}
// 用户组权限
int getgrPrem(Stat *pstat, char *info)
{
// 获取结构体成员的值
mode_t mode = pstat->st_mode; // 40542
printf("用户组权限\n");
int perm = mode & S_IRWXG; // 获取用户组权限位
switch (perm)
{
case S_IRWXG:
strcat(info, "rwx");
break;
case S_IRGRP:
strcat(info, "r--");
break;
case S_IWGRP:
strcat(info, "-w-");
break;
case S_IXGRP:
strcat(info, "--x");
break;
case (S_IRGRP | S_IWGRP):
strcat(info, "rw-");
break;
case (S_IXGRP | S_IWGRP):
strcat(info, "-wx");
break;
case (S_IXGRP | S_IRGRP):
strcat(info, "r-x");
break;
default:
strcat(info, "---");
break;
}
// 返回一些值,这里假设返回1表示成功
return 1;
}
// 其他用户
int getgrrPrem(Stat *pstat, char *info)
{
// 获取结构体成员的值
mode_t mode = pstat->st_mode; // 40542
printf("其他用户权限\n");
int perm = mode & S_IRWXO; // 获取用户组权限位
switch (perm)
{
case S_IRWXO:
strcat(info, "rwx");
break;
case S_IROTH:
strcat(info, "r--");
break;
case S_IWOTH:
strcat(info, "-w-");
break;
case S_IXOTH:
strcat(info, "--x");
break;
case (S_IROTH | S_IWOTH):
strcat(info, "rw-");
break;
case (S_IXOTH | S_IWOTH):
strcat(info, "-wx");
break;
case (S_IXOTH | S_IROTH):
strcat(info, "r-x");
break;
default:
strcat(info, "---");
break;
}
// 返回一些值,这里假设返回1表示成功
return 1;
}
// 6.获取文件的所属名称
int getOwnerName(Stat *pstat, char *info)
{
// 获取所属用户的uid
uid_t uid = pstat->st_uid;
// 调用函数通过用户id获取用户名称
struct passwd *passwd_p = getpwuid(uid);
// 获取结构体成员中的name
char *uname = passwd_p->pw_name;
strcat(info, " ");
// 将用户名拼接到字符串中
strcat(info, uname);
}
// 7.获取文件所属组名称
int getOwnerGroupName(Stat *pstat, char *info)
{
// 获取所属组的gid
gid_t gid = pstat->st_gid;
// 调用函数通过组id获取组信息
struct group *grp_p = getgrgid(gid);
if (grp_p == NULL)
{
strcat(info, " [unknown group]");
return -1; // 返回错误码表示失败
}
// 获取结构体成员中的组名
char *gname = grp_p->gr_name;
// 在info字符串中添加空格和组名
strcat(info, " ");
strcat(info, gname);
return 0;
}
header.c
#ifndef _HEARD_H
#define _HEARD_H
// 常用头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// access, read, write, lseek, stat
#include <unistd.h>
// open, lseek, stat, getpwuid
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <grp.h>
// mmap, munmap
#include <sys/mman.h>
// getpwuid
#include <pwd.h>
typedef struct stat Stat;
// 1.获取文件的类型
int getFileType(Stat *pstat, char *info);
int getOwnerPrem(Stat *pstat, char *info);
int getgrPrem(Stat *pstat, char *info);
int getgrrPrem(Stat *pstat, char *info);
// 6.获取文件的所属名称
int getOwnerName(Stat *pstat, char *info);
int getOwnerGroupName(Stat *pstat, char *info);
#endif
main.c
#include <stdio.h>
#include "header.h"
int main(int argc, char const *argv[])
{
if (argc < 2)
{
puts("缺少参数");
return -1;
}
puts(argv[1]);
// 调用stat函数获取文件的状态信息
Stat fstat = {0};
// int r = stat(argv[1], &fstat);
int r = lstat(argv[1], &fstat);
if (r == -1)
{
perror("stat failed");
return -1;
}
// 定义一个数组,用于凭借文件的状态信息:-rwxrwxrwx 1 root root 2250 1月 9 15:08 07-touch-screen.c
char info[100] = {0};
// 1.调用函数获取文件的类型并拼接的info中
getFileType(&fstat, info);
// 2.获取文件用户者的权限
getOwnerPrem(&fstat, info);
// 3.获取同组用户的权限---自学
getgrPrem(&fstat, info);
// 4.获取不同组的其他用户权限---自学
getgrrPrem(&fstat, info);
// 5.获取链接数量
// 6.获取文件所属用户名称
getOwnerName(&fstat, info);
// 7.获取文件所属组名称---自学
getOwnerGroupName(&fstat, info);
// 打印文件信息
puts(info);
return 0;
}
标签:info,文件,编程,strcat,char,mode,触屏,event,ls
From: https://blog.csdn.net/weixin_69851948/article/details/145042429