lseek() sample program in C

本文介绍了文件系统中如何使用lseek系统调用来改变文件的读写位置,包括其基本用法、返回值及错误处理等内容,并深入探讨了在设备驱动程序中llseek方法的实现细节。
Input and output are normally sequential: each read or write takes place at a position in the file right after the previous one. When necessary, however, a file can be read or written in any arbitrary order. The system call lseek provides a way to move around in a file without reading or writing any data:
   long lseek(int fd, long offset, int origin);
sets the current position in the file whose descriptor is fd to offset, which is taken relative to the location specified by origin. Subsequent reading or writing will begin at that position. origin can be 0, 1, or 2 to specify that offset is to be measured from the beginning, from the current position, or from the end of the file respectively. For example, to append to a file (the redirection >> in the UNIX shell, or "a" for fopen), seek to the end before writing:
   lseek(fd, 0L, 2);
To get back to the beginning (``rewind''),
   lseek(fd, 0L, 0);
Notice the 0L argument; it could also be written as (long) 0 or just as 0 if lseek is properly declared.

With lseek, it is possible to treat files more or less like arrays, at the price of slower access. For example, the following function reads any number of bytes from any arbitrary place in a file. It returns the number read, or-1 on error.

   #include "syscalls.h"

   /*get:  read n bytes from position pos */
   int get(int fd, long pos, char *buf, int n)
   {
       if (lseek(fd, pos, 0) >= 0) /* get to pos */
           return read(fd, buf, n);
       else
           return -1;
   }

The return value from lseek is a long that gives the new position in the file, or-1 if an error occurs. The standard library function fseek is similar tolseek except that the first argument is a FILE * and the return is non-zero if an error occurred.

====

http://www.java-samples.com/showtutorial.php?tutorialid=571

 

----------------------------------------------------------------------------------------------------------------------------

6.5. 移位一个设备

本章最后一个需要我们涉及的东西是 llseek 方法, 它有用(对于某些设备)并且容易实现.

6.5.1. llseek 实现

llseek 方法实现了 lseek 和 llseek 系统调用. 我们已经说了如果 llseek 方法从设备的操作中缺失, 内核中的缺省的实现进行移位通过修改 filp->f_pos, 这是文件中的当前读写位置. 请注意对于 lseek 系统调用要正确工作, 读和写方法必须配合, 通过使用和更新它们收到的作为的参数的 offset 项.

你可能需要提供你自己的方法, 如果移位操作对应一个在设备上的物理操作. 一个简单的例子可在 scull 驱动中找到:

loff_t scull_llseek(struct file *filp, loff_t off, int whence)
{
        struct scull_dev *dev = filp->private_data;
        loff_t newpos;

        switch(whence)
        {
        case 0: /* SEEK_SET */
                newpos = off;
                break;

        case 1: /* SEEK_CUR */
                newpos = filp->f_pos + off;
                break;

        case 2: /* SEEK_END */
                newpos = dev->size + off;
                break;

        default: /* can't happen */
                return -EINVAL;
        }
        if (newpos < 0)
                return -EINVAL;
        filp->f_pos = newpos;
        return newpos;
}

唯一设备特定的操作是从设备中获取文件长度. 在 scull 中 read 和 write 方法如需要地一样协作, 如同在第 3 章所示.

尽管刚刚展示的这个实现对 scull 有意义, 它处理一个被很好定义了的数据区, 大部分设备提供了一个数据流而不是一个数据区(想想串口或者键盘), 并且移位这些设备没有意义. 如果这就是你的设备的情况, 你不能只制止声明 llseek 操作, 因为缺省的方法允许移位. 相反, 你应当通知内核你的设备不支持 llseek , 通过调用 nonseekable_open 在你的 open 方法中.

int nonseekable_open(struct inode *inode; struct file *filp); 

这个调用标识了给定的 filp 为不可移位的; 内核从不允许一个 lseek 调用在这样一个文件上成功. 通过用这样的方式标识这个文件, 你可确定不会有通过 pread 和 pwrite 系统调用的方式来试图移位这个文件.

完整起见, 你也应该在你的 file_operations 结构中设置 llseek 方法到一个特殊的帮忙函数 no_llseek, 它定义在 <linux/fs.h>.

====

http://oss.org.cn/kernel-book/ldd3/ch06s05.html

根据我的gprof结果 来改进代码结果如下Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls s/call s/call name 42.79 1.96 1.96 1 1.96 3.28 func1 28.82 3.28 1.32 1 1.32 1.32 new_func1 28.38 4.58 1.30 1 1.30 1.30 func2 % the percentage of the total running time of the time program used by this function. cumulative a running sum of the number of seconds accounted seconds for by this function and those listed above it. self the number of seconds accounted for by this seconds function alone. This is the major sort for this listing. calls the number of times this function was invoked, if this function is profiled, else blank. self the average number of milliseconds spent in this ms/call function per call, if this function is profiled, else blank. total the average number of milliseconds spent in this ms/call function and its descendents per call, if this function is profiled, else blank. name the name of the function. This is the minor sort for this listing. The index shows the location of the function in the gprof listing. If the index is in parenthesis it shows where it would appear in the gprof listing if it were to be printed. Copyright (C) 2012-2022 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. Call graph (explanation follows) granularity: each sample hit covers 4 byte(s) for 0.22% of 4.58 seconds index % time self children called name <spontaneous> [1] 100.0 0.00 4.58 main [1] 1.96 1.32 1/1 func1 [2] 1.30 0.00 1/1 func2 [4] ----------------------------------------------- 1.96 1.32 1/1 main [1] [2] 71.6 1.96 1.32 1 func1 [2] 1.32 0.00 1/1 new_func1 [3] ----------------------------------------------- 1.32 0.00 1/1 func1 [2] [3] 28.8 1.32 0.00 1 new_func1 [3] ----------------------------------------------- 1.30 0.00 1/1 main [1] [4] 28.4 1.30 0.00 1 func2 [4] ----------------------------------------------- This table describes the call tree of the program, and was sorted by the total amount of time spent in each function and its children. Each entry in this table consists of several lines. The line with the index number at the left hand margin lists the current function. The lines above it list the functions that called this function, and the lines below it list the functions this one called. This line lists: index A unique number given to each element of the table. Index numbers are sorted numerically. The index number is printed next to every function name so it is easier to look up where the function is in the table. % time This is the percentage of the `total' time that was spent in this function and its children. Note that due to different viewpoints, functions excluded by options, etc, these numbers will NOT add up to 100%. self This is the total amount of time spent in this function. children This is the total amount of time propagated into this function by its children. called This is the number of times the function was called. If the function called itself recursively, the number only includes non-recursive calls, and is followed by a `+' and the number of recursive calls. name The name of the current function. The index number is printed after it. If the function is a member of a cycle, the cycle number is printed between the function's name and the index number. For the function's parents, the fields have the following meanings: self This is the amount of time that was propagated directly from the function into this parent. children This is the amount of time that was propagated from the function's children into this parent. called This is the number of times this parent called the function `/' the total number of times the function was called. Recursive calls to the function are not included in the number after the `/'. name This is the name of the parent. The parent's index number is printed after it. If the parent is a member of a cycle, the cycle number is printed between the name and the index number. If the parents of the function cannot be determined, the word `<spontaneous>' is printed in the `name' field, and all the other fields are blank. For the function's children, the fields have the following meanings: self This is the amount of time that was propagated directly from the child into the function. children This is the amount of time that was propagated from the child's children to the function. called This is the number of times the function called this child `/' the total number of times the child was called. Recursive calls by the child are not listed in the number after the `/'. name This is the name of the child. The child's index number is printed after it. If the child is a member of a cycle, the cycle number is printed between the name and the index number. If there are any cycles (circles) in the call graph, there is an entry for the cycle-as-a-whole. This entry shows who called the cycle (as parents) and the members of the cycle (as children.) The `+' recursive calls entry shows the number of function calls that were internal to the cycle, and the calls entry for each member shows, for that member, how many times it was called from other members of the cycle. Copyright (C) 2012-2022 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. Index by function name [2] func1 [4] func2 [3] new_func1代码如下#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> typedef struct { unsigned char r, g, b; } Pixel; // 前置声明 static int readPPM(const char *filename, int *width, int *height, int *max_val, Pixel **pixels); static int writePPM(const char *filename, int width, int height, int max_val, const Pixel *pixels); static void grayscale(Pixel *pixels, int num_pixels); int main() { int width, height, max_val; Pixel *pixels = NULL; if (!readPPM("im.ppm", &width, &height, &max_val, &pixels)) { fprintf(stderr, "Error: Failed to read input file\n"); return EXIT_FAILURE; } const int num_pixels = width * height; grayscale(pixels, num_pixels); if (!writePPM("im-gray.ppm", width, height, max_val, pixels)) { fprintf(stderr, "Error: Failed to write output file\n"); free(pixels); return EXIT_FAILURE; } free(pixels); printf("Conversion completed. Output: im-gray.ppm\n"); return EXIT_SUCCESS; } static int readPPM(const char *filename, int *width, int *height, int *max_val, Pixel **pixels) { FILE *file = fopen(filename, "r"); if (!file) { fprintf(stderr, "Error opening %s: %s\n", filename, strerror(errno)); return 0; } char magic[3]; if (fscanf(file, "%2s", magic) != 1 || strcmp(magic, "P3") != 0) { fprintf(stderr, "Invalid PPM format. Expected P3\n"); fclose(file); return 0; } // 读取图像元数据 if (fscanf(file, "%d %d %d", width, height, max_val) != 3) { fprintf(stderr, "Invalid image header\n"); fclose(file); return 0; } const int num_pixels = *width * *height; *pixels = malloc(num_pixels * sizeof(Pixel)); if (!*pixels) { fprintf(stderr, "Memory allocation failed for %d pixels\n", num_pixels); fclose(file); return 0; } // 批量读取像素数据 for (int i = 0; i < num_pixels; i++) { int r, g, b; if (fscanf(file, "%d %d %d", &r, &g, &b) != 3) { fprintf(stderr, "Invalid pixel data at #%d\n", i); free(*pixels); *pixels = NULL; fclose(file); return 0; } (*pixels)[i] = (Pixel){ (unsigned char)r, (unsigned char)g, (unsigned char)b }; } fclose(file); return 1; } static int writePPM(const char *filename, int width, int height, int max_val, const Pixel *pixels) { FILE *file = fopen(filename, "w"); if (!file) { fprintf(stderr, "Error creating %s: %s\n", filename, strerror(errno)); return 0; } // 使用大缓冲区提高I/O性能 char buffer[8192]; setvbuf(file, buffer, _IOFBF, sizeof(buffer)); fprintf(file, "P3\n%d %d\n%d\n", width, height, max_val); const int num_pixels = width * height; for (int i = 0; i < num_pixels; i++) { if (fprintf(file, "%d %d %d\n", pixels[i].r, pixels[i].g, pixels[i].b) < 0) { fprintf(stderr, "Write error at pixel #%d\n", i); fclose(file); return 0; } } fclose(file); return 1; } static void grayscale(Pixel *pixels, int num_pixels) { Pixel *current = pixels; const Pixel *end = pixels + num_pixels; while (current < end) { const unsigned char gray = (current->r + current->g + current->b) / 3; *current++ = (Pixel){ gray, gray, gray }; } }
10-15
【轴承故障诊断】基于融合鱼鹰和柯西变异的麻雀优化算法OCSSA-VMD-CNN-BILSTM轴承诊断研究【西储大学数据】(Matlab代码实现)内容概要:本文提出了一种基于融合鱼鹰和柯西变异的麻雀优化算法(OCSSA)优化变分模态分解(VMD)参数,并结合卷积神经网络(CNN)与双向长短期记忆网络(BiLSTM)的轴承故障诊断模型。该方法利用西储大学公开的轴承数据集进行验证,通过OCSSA算法优化VMD的分解层数K和惩罚因子α,有效提升信号分解精度,抑制模态混叠;随后利用CNN提取故障特征的空间信息,BiLSTM捕捉时间序列的动态特征,最终实现高精度的轴承故障分类。整个诊断流程充分结合了信号预处理、智能优化与深度学习的优势,显著提升了复杂工况下轴承故障诊断的准确性与鲁棒性。; 适合人群:具备一定信号处理、机器学习及MATLAB编程基础的研究生、科研人员及从事工业设备故障诊断的工程技术人员。; 使用场景及目标:①应用于旋转机械设备的智能运维与故障预警系统;②为轴承等关键部件的早期故障识别提供高精度诊断方案;③推动智能优化算法与深度学习在工业信号处理领域的融合研究。; 阅读建议:建议读者结合MATLAB代码实现,深入理解OCSSA优化机制、VMD参数选择策略以及CNN-BiLSTM网络结构的设计逻辑,通过复现实验掌握完整诊断流程,并可进一步尝试迁移至其他设备的故障诊断任务中进行验证与优化。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值