【Linux】C语言系统函数实现touch命令

 🔥博客主页: 我要成为C++领域大神

🎥系列专栏【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】

❤️感谢大家点赞👍收藏⭐评论✍️

本博客致力于分享知识,欢迎大家共同学习和交流。

touch 是一个常用的命令行工具,在 Linux 和类 Unix 系统中使用。它主要用于创建空文件或者修改文件的访问时间(atime)和修改时间(mtime)。

创建空文件:如果指定的文件不存在,touch 命令会创建一个空的文件。如果文件已经存在,touch 命令会更新文件的访问时间和修改时间。

touch filename

同时创建多个文件touch 命令可以同时创建多个文件。

touch file1 file2 file3

指定时间:使用 -t 选项可以指定文件的访问时间和修改时间。

touch -t YYYYMMDDHHMM.SS filename

使用其他文件的时间戳:使用 -r 选项可以使用其他文件的时间戳来设置指定文件的时间戳。

touch -r reference_file filename

只更新时间戳:使用 -c 选项可以只更新文件的时间戳,而不创建新文件。

touch -c filename

我们将用Linux系统函数中的open实现简单的touch命令:创建空文件、同时创建多个文件

先来了解一下open函数

open

1、功能:打开或创建一个文件。

2、头文件:

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

3、函数定义:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

4、返回值:成功返回新分配的文件描述符,出错返回-1并设置errno

5、参数说明:

pathname参数是要打开或创建的文件名,可以是相对路径也可以是绝对路径。

flags参数有一系列常数值可供选择,可以同时选择多个常数用按位或运算符连接起来,所以这些常

数的宏定义都以O_开头,表示or。

必选项:以下三个常数中必须指定一个,且仅允许指定一个。

O_RDONLY:只读打开

O_WRONLY:只写打开

O_RDWR:可读可写打开

以下可选项可以同时指定0个或多个,和必选项按位或起来作为flags参数。

O_APPEND:表示追加。如果文件已有内容,这次打开文件所写的数据附加到文件的末尾而不覆盖

原来的内容。

O_CREAT:若此文件不存在则创建它。使用此选项时需要提供第三个参数mode,表示该文件的访

问权限。

O_EXCL:如果同时指定了O_CREAT,并且文件已存在,则出错返回。

O_TRUNC:如果文件已存在,并且以只写或可读可写方式打开,则将其长度截断(Trun-cate)为

0字节。

O_NONBLOCK:对于设备文件,以O_NONBLOCK方式打开可以做非阻塞I/O(Nonblock I/ O)

mode指定文件权限,可以用八进制数表示,比如0644表示-rw-r--r--

那么了解完open函数之后,想要实现简单的touch命令,我们需要调用open函数int open(const char *pathname, int flags, mode_t mode);并将第二个参数设置为O_CREAT,文件不存在则创建。
如果同时创建多个文件的话,那么需要循环创建。

main函数的“参数”

在此之前,我们需要先了解一下main函数的参数。
main函数也是有参数的。

int main(int argc, char *argv[])
{
    return 0;
}

char *argv[]:很明显,这是一个数组,char *类型的数组,数组内每个元素都是一个字符串
argc:数组的长度,即字符串的个数。

代表的是我们在终端输入命令时,读取到的命令的个数,按空格来区分。

a7051967986c62c8dcb532ed2bcfd8d4.png

例如一个简单的touch命令,argc=4,argv={"touch","aa","bb","cc"}。

函数实现

了解完原理之后,我们开始实现

第一步,需要判断命令是否合法,因为要创建文件至少需要两个参数(touch filename)

第二步,如果我们有多个文件则需要循环进行创建,需要用到for循环

第三步,open函数每建一个文件都会分配一个文件描述符,我们可以用返回值来判断是否创建成功

第四步,操作系统中可以打开的文件是有上限的,所以我们在创建之后,需要进行关闭。

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

int main(int argc,char * argv[]){
//1、判断命令是否合法
        if(argc<2) return -1;
//2、循环创建文件
     for(int i=1;i<argc;++i){
        int fd=open(argv[i],O_CREAT,0777);
//3、根据文件描述符,判断是否创建成功
        if(fd==-1){
        printf("file %s created fail ",argv[i]);
        continue;
//4、关闭打开的文件
        close(fd);
        }

}
        return 0;

}

创建一个文件:

bd2cb2399599627e55aed296b85898e2.png

成功创建!

创建多个文件:

462ee1ee77a5d80b0a5bb2f151d41f19.png

成功创建

默认掩码

为什么open函数的第三个参数,mode,我们传入的是0777,但是实际创建的确实0755?

因为系统有默认的掩码,对权限进行遮掩。我们在函数中用umask修改一下即可。

e3ee07df46b7feac6766161c8ab16d09.png

再次创建文件查看权限:

3144ebb919cd8b20036f20e9555c171c.png

修改成功!

  • 43
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是基于Linux下的C语言实现的示例代码: 1. 引入相关头文件 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <linux/input.h> #include <sys/mman.h> #include <errno.h> #include <stdbool.h> #include <time.h> #include <SDL/SDL.h> #include <SDL/SDL_image.h> #include <SDL/SDL_ttf.h> ``` 需要安装SDL、SDL_image和SDL_ttf库。 2. 定义常量 ```c #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define IMAGE_WIDTH 320 #define IMAGE_HEIGHT 240 #define IMAGE_NUM 4 #define IMAGE_PATH "./image%d.bmp" ``` 定义屏幕宽度、高度、图片宽度、高度、图片数量和图片路径等常量。 3. 定义全局变量 ```c int touch_fd; int screen_fd; int *screen_mem; int current_image_index = 0; SDL_Surface *screen; SDL_Surface *images[IMAGE_NUM]; ``` 定义触摸屏文件描述符、屏幕文件描述符、屏幕内存映射指针、当前显示图片的索引和SDL界面和图片数组等全局变量。 4. 定义函数 ```c int init_touch_screen(); int init_screen(); int init_images(); void show_image(int index); void switch_image(int index); ``` 定义初始化触摸屏、初始化屏幕、初始化图片、显示图片和切换图片等函数。 5. 实现函数 ```c int init_touch_screen() { touch_fd = open("/dev/input/event0", O_RDONLY); if(touch_fd < 0) { printf("Open touch screen device failed.\n"); return -1; } return 0; } int init_screen() { screen_fd = open("/dev/fb0", O_RDWR); if(screen_fd < 0) { printf("Open screen device failed.\n"); return -1; } screen_mem = mmap(NULL, SCREEN_WIDTH * SCREEN_HEIGHT * 4, PROT_READ | PROT_WRITE, MAP_SHARED, screen_fd, 0); if(screen_mem == MAP_FAILED) { printf("Map screen memory failed.\n"); return -1; } screen = SDL_CreateRGBSurfaceFrom(screen_mem, SCREEN_WIDTH, SCREEN_HEIGHT, 32, SCREEN_WIDTH * 4, 0, 0, 0, 0); if(screen == NULL) { printf("Create screen surface failed.\n"); return -1; } SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); SDL_UpdateRect(screen, 0, 0, 0, 0); return 0; } int init_images() { int i; char image_path[64]; for(i = 0; i < IMAGE_NUM; i++) { sprintf(image_path, IMAGE_PATH, i + 1); images[i] = IMG_Load(image_path); if(images[i] == NULL) { printf("Load image %s failed: %s.\n", image_path, IMG_GetError()); return -1; } } return 0; } void show_image(int index) { SDL_Rect src_rect; SDL_Rect dest_rect; src_rect.x = 0; src_rect.y = 0; src_rect.w = IMAGE_WIDTH; src_rect.h = IMAGE_HEIGHT; dest_rect.x = (SCREEN_WIDTH - IMAGE_WIDTH) / 2; dest_rect.y = (SCREEN_HEIGHT - IMAGE_HEIGHT) / 2; dest_rect.w = IMAGE_WIDTH; dest_rect.h = IMAGE_HEIGHT; SDL_BlitSurface(images[index], &src_rect, screen, &dest_rect); SDL_UpdateRect(screen, 0, 0, 0, 0); } void switch_image(int index) { int i, j; SDL_Rect src_rect; SDL_Rect dest_rect; src_rect.x = 0; src_rect.y = 0; src_rect.w = IMAGE_WIDTH; src_rect.h = IMAGE_HEIGHT; dest_rect.x = (SCREEN_WIDTH - IMAGE_WIDTH) / 2; dest_rect.y = (SCREEN_HEIGHT - IMAGE_HEIGHT) / 2; dest_rect.w = IMAGE_WIDTH; dest_rect.h = IMAGE_HEIGHT; if(index == current_image_index) { return; } if(index > current_image_index) { for(i = current_image_index; i < index; i++) { SDL_BlitSurface(images[i], &src_rect, screen, &dest_rect); SDL_UpdateRect(screen, 0, 0, 0, 0); for(j = 1; j <= IMAGE_HEIGHT; j++) { SDL_BlitSurface(images[i + 1], &src_rect, screen, &dest_rect); SDL_UpdateRect(screen, 0, 0, 0, 0); SDL_Delay(2); dest_rect.y--; } } } else { for(i = current_image_index; i > index; i--) { SDL_BlitSurface(images[i], &src_rect, screen, &dest_rect); SDL_UpdateRect(screen, 0, 0, 0, 0); for(j = 1; j <= IMAGE_HEIGHT; j++) { SDL_BlitSurface(images[i - 1], &src_rect, screen, &dest_rect); SDL_UpdateRect(screen, 0, 0, 0, 0); SDL_Delay(2); dest_rect.y++; } } } current_image_index = index; } ``` 实现初始化触摸屏、初始化屏幕、初始化图片、显示图片和切换图片等函数。 6. 实现函数 ```c int main(int argc, char *argv[]) { int x, y; bool touch_down = false; int touch_down_x, touch_down_y; struct input_event touch_event; if(init_touch_screen() < 0) { return -1; } if(init_screen() < 0) { return -1; } if(init_images() < 0) { return -1; } show_image(current_image_index); while(true) { if(read(touch_fd, &touch_event, sizeof(touch_event)) == sizeof(touch_event)) { if(touch_event.type == EV_ABS) { if(touch_event.code == ABS_X) { x = (touch_event.value - 200) * SCREEN_WIDTH / 620; } else if(touch_event.code == ABS_Y) { y = (touch_event.value - 200) * SCREEN_HEIGHT / 380; } } else if(touch_event.type == EV_KEY) { if(touch_event.code == BTN_TOUCH) { touch_down = touch_event.value; if(touch_down) { touch_down_x = x; touch_down_y = y; } else { if(x < SCREEN_WIDTH / 2 && y < SCREEN_HEIGHT / 2) { switch_image(0); } else if(x < SCREEN_WIDTH / 2 && y >= SCREEN_HEIGHT / 2) { switch_image(1); } else if(x >= SCREEN_WIDTH / 2 && y < SCREEN_HEIGHT / 2) { switch_image(2); } else { switch_image(3); } } } } } } return 0; } ``` 实现函数,监听触摸屏的事件,根据触摸屏的位置切换图片,并实现图片切换效果。 7. 编译运行程序 使用以下命令编译程序: ``` gcc -o touch_screen touch_screen.c -lSDL -lSDL_image -lSDL_ttf ``` 使用以下命令运行程序: ``` sudo ./touch_screen ``` 8. 效果展示 当触摸屏位于左上区域时,显示image1.bmp图片并实现掉落效果;当触摸屏位于左下区域时,显示image2.bmp图片并实现滚动效果;当触摸屏位于右上区域时,显示image3.bmp图片并实现掉落效果;当触摸屏位于右下区域时,显示image4.bmp图片并实现滚动效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值