<Linux> Linux Driver文件读取

本文提供了一个在Linux环境下使用C语言实现的文件读取示例。通过此示例,读者可以了解到如何打开一个文件、读取文件内容,并正确关闭文件。此外,还展示了如何处理读取过程中可能出现的错误。
void driver_read_file(const char *filename)
{
	struct file *pfile;
	mm_segment_t old_fs;
	char read_buf[100] = {0};
	struct inode *inode;
	int ret;
	off_t fsize;
	int pkg_size = 64;
	int left;
	int read_size;

	pfile = filp_open(filename, O_RDONLY, 0);

	if (IS_ERR(pfile)) {
		pr_err("Open %s failed!\n", filename);
		return;
	}
	old_fs = get_fs();
	set_fs(KERNEL_DS);

	inode = pfile->f_dentry->d_inode;
	fsize = inode->i_size;

	pr_err("file size: %ld bytes\n", fsize);
	pr_err("file content: \n");
	left = fsize;
	while (left > 0) {
		if (left > pkg_size) {
			read_size = pkg_size;
		}
		else {
			read_size = left;
		}
		ret = pfile->f_op->read(pfile, read_buf, read_size, &pfile->f_pos);
		if (ret < 0) {
			pr_err("read data failed, ret: %d\n", ret);

			filp_close(pfile, NULL);
			set_fs(old_fs);
			return;
		}
		pr_err("%s\n", read_buf);
		left -= read_size;
	}
	filp_close(pfile, NULL);
	set_fs(old_fs);
}

任务描述 本关任务:根据编程要求,完成任务。 编程要求 编写独立应用程序,读取 Linux 系统本地文件 /data/bigfiles/test.txt,然后统计出文件的行数;通过 maven 工具将整个应用程序编译打包成 JAR 包,并将生成的 JAR 包通过 spark-submit 提交到 Spark 中运行,将运行结果保存到 /root/maven_result.txt 文件中。 示例 pom.xml 文件如下: <project> <groupId>cn.edu.xmu</groupId> <artifactId>simple-project</artifactId> <modelVersion>4.0.0</modelVersion> <name>Simple Project</name> <packaging>jar</packaging> <version>1.0</version> <repositories> <repository> <id>jboss</id> <name>JBoss Repository</name> <url>http://repository.jboss.com/maven2/</url> </repository> </repositories> <dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.11</artifactId> <version>2.1.0</version> </dependency> </dependencies> <build> <sourceDirectory>src/main/scala</sourceDirectory> <plugins> <plugin> <groupId>org.scala-tools</groupId> <artifactId>maven-scala-plugin</artifactId> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> <configuration> <scalaVersion>2.11.8</scalaVersion> <args> <arg>-target:jvm-1.5</arg> </args> </configuration> </plugin> </plugins> </build> </project> 测试说明 平台将对你编写的代码进行评测,如果与预期结果一致,则通关,否则测试失败。 开始你的任务吧,祝你成功!
最新发布
11-18
<think> 我们被要求编写一个独立的Spark应用程序,该程序读取本地Linux文件(/data/bigfiles/test.txt),统计行数,然后使用Maven打包成JAR包,最后通过spark-submit提交运行并将结果保存到/root/maven_result.txt。 步骤分解: 1. 编写Scala程序:使用Spark读取本地文件,统计行数,并将结果保存到指定路径。 2. 使用Maven管理项目并打包成JAR。 3. 使用spark-submit提交任务,并指定输出路径。 注意:由于是本地文件,Spark在读取时需要使用本地文件系统路径(file://)。另外,保存结果时也要使用本地文件系统路径。 具体步骤: 一、创建Maven项目并编写代码 1. 使用IDE(如IntelliJ IDEA)创建一个Maven项目,选择Scala作为语言。 2. 在pom.xml中添加Spark依赖和打包插件。 pom.xml示例: ```xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spark-line-count</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <scala.version>2.12.15</scala.version> <spark.version>3.2.1</spark.version> </properties> <dependencies> <!-- Scala --> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>${scala.version}</version> </dependency> <!-- Spark Core --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.12</artifactId> <version>${spark.version}</version> </dependency> </dependencies> <build> <plugins> <!-- 用于编译Scala的插件 --> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>4.5.6</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> <!-- 打包插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.example.LineCount</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> ``` 3. 编写Scala代码 在src/main/scala下创建包(如com.example),然后创建LineCount.scala。 ```scala package com.example import org.apache.spark.sql.SparkSession object LineCount { def main(args: Array[String]): Unit = { // 创建SparkSession val spark = SparkSession.builder() .appName("LineCount") .master("local[*]") // 本地模式,使用所有可用核心 .getOrCreate() // 读取本地文件(注意:使用file://协议) val filePath = "file:///data/bigfiles/test.txt" val lines = spark.sparkContext.textFile(filePath) // 统计行数 val count = lines.count() // 打印结果到控制台(可选) println(s"文件行数为: $count") // 将结果保存到本地文件(注意:保存到本地也需要file://) // 由于结果是一个数字,我们将其转换为RDD再保存 spark.sparkContext.parallelize(Seq(count)).coalesce(1) .saveAsTextFile("file:///root/maven_result.txt") // 停止SparkSession spark.stop() } } ``` 注意:这里我们使用本地模式(master("local[*]"))运行,因为我们的输入输出都是本地文件。如果要在集群上运行,需要修改为集群模式,但注意集群节点必须能访问到本地文件(通常不行),所以这里我们使用本地模式。但根据需求,我们是通过spark-submit提交,可以在提交时指定master,所以这里也可以不在代码中写死master,而是通过spark-submit的--master参数指定。 二、使用Maven打包 在项目根目录下运行: ```bash mvn clean package ``` 打包成功后,会在target目录下生成两个jar包,其中包含依赖的jar包名字类似`spark-line-count-1.0-SNAPSHOT-jar-with-dependencies.jar`。 三、提交任务 使用spark-submit提交任务。由于我们的输入输出都是本地文件,所以需要在提交任务的那台机器上有这个文件(/data/bigfiles/test.txt)并且有写入/root目录的权限。而且,我们使用本地模式运行,所以master设置为local。 ```bash spark-submit \ --class com.example.LineCount \ --master local[*] \ /path/to/spark-line-count-1.0-SNAPSHOT-jar-with-dependencies.jar ``` 但是,注意:我们的程序并没有指定输入输出路径为参数,而是写死在代码中。为了灵活,我们可以通过命令行参数传递输入输出路径。 改进代码: 修改LineCount.scala,从命令行参数获取输入输出路径: ```scala package com.example import org.apache.spark.sql.SparkSession object LineCount { def main(args: Array[String]): Unit = { if (args.length < 2) { println("Usage: LineCount <inputPath> <outputPath>") System.exit(1) } val inputPath = args(0) val outputPath = args(1) val spark = SparkSession.builder() .appName("LineCount") .getOrCreate() // 不在这里设置master,而是通过spark-submit的参数指定 val lines = spark.sparkContext.textFile(inputPath) val count = lines.count() // 将结果保存为一个文件 spark.sparkContext.parallelize(Seq(count)).coalesce(1) .saveAsTextFile(outputPath) spark.stop() } } ``` 然后重新打包。 提交命令: ```bash spark-submit \ --class com.example.LineCount \ --master local[*] \ /path/to/spark-line-count-1.0-SNAPSHOT-jar-with-dependencies.jar \ "file:///data/bigfiles/test.txt" "file:///root/maven_result.txt" ``` 注意:输入和输出路径都使用完整的URI,包括`file://`。 这样,Spark就会读取本地的`/data/bigfiles/test.txt`,统计行数,然后将结果(一个数字)写入到`/root/maven_result.txt`目录(注意:Spark保存输出是一个目录,里面会有一个或多个文件,因为并行保存)。但是我们通过coalesce(1)将其合并为一个文件,所以会在`/root/maven_result.txt`目录下生成一个文件(如part-00000)。 如果希望结果直接是一个文件,而不是目录,我们可以将结果收集到Driver然后使用单文件输出(例如用Java的文件IO),但是这样对于大结果集不适用。不过这里我们只有一个数字,所以也可以这样做: ```scala // 将结果收集到Driver val count = lines.count() // 使用Java IO写入文件 import java.io.PrintWriter new PrintWriter(outputPath) { write(count.toString); close() } ``` 但是这样输出路径就不是目录而是一个文件。注意:此时输出路径就不能再带`file://`前缀了,因为我们是直接使用本地文件系统API。 修改后的代码: ```scala package com.example import org.apache.spark.sql.SparkSession import java.io.PrintWriter object LineCount { def main(args: Array[String]): Unit = { if (args.length < 2) { println("Usage: LineCount <inputPath> <outputFile>") System.exit(1) } val inputPath = args(0) // 可以是本地路径(file://)或者HDFS路径(hdfs://) val outputFile = args(1) // 本地文件路径(不需要file://) val spark = SparkSession.builder() .appName("LineCount") .getOrCreate() // 读取文件 val lines = spark.sparkContext.textFile(inputPath) val count = lines.count() // 将结果写入本地文件(使用Java IO) new PrintWriter(outputFile) { write(count.toString); close() } spark.stop() } } ``` 提交命令(输入路径还是用file://,输出路径直接写本地路径): ```bash spark-submit \ --class com.example.LineCount \ --master local[*] \ /path/to/spark-line-count-1.0-SNAPSHOT-jar-with-dependencies.jar \ "file:///data/bigfiles/test.txt" "/root/maven_result.txt" ``` 这样,结果就会直接写入`/root/maven_result.txt`文件(不是目录)。 注意:这种方法适用于小结果,因为Driver需要收集结果。对于大结果,应该使用RDD的saveAsTextFile保存到分布式文件系统。 由于我们的结果只是一个数字,所以这种方法可行。 总结步骤: 1. 创建Maven项目,配置pom.xml。 2. 编写Scala程序,从命令行参数获取输入和输出路径,读取输入文件统计行数,然后将结果写入输出文件(使用PrintWriter)。 3. 使用mvn package打包。 4. 使用spark-submit提交,指定输入和输出路径。 注意:确保运行spark-submit的用户有权限读取输入文件和写入输出文件。 如果运行在集群模式(非本地模式),那么输入输出路径应该使用分布式文件系统(如HDFS),并且Driver程序可能运行在任意节点,使用本地文件路径可能会找不到。但根据需求,我们读取的是本地文件Linux系统本地文件),所以必须使用本地模式(--master local[*])运行,并且确保提交任务的机器上有该文件。 如果文件在集群的所有节点上都有(且路径相同),那么也可以使用集群模式,但是需要在每个节点上都有该文件,并且使用`file://`路径。但通常我们不会这样做,所以本地模式是最简单的。 因此,我们选择在本地模式运行。 </think>### 编写独立Spark应用程序统计本地文件行数的方法 #### 1. 编写Scala应用程序代码 创建一个名为`LocalFileLineCount.scala`的文件,包含以下内容: ```scala import org.apache.spark.sql.SparkSession object LocalFileLineCount { def main(args: Array[String]): Unit = { // 创建SparkSession val spark = SparkSession.builder() .appName("LocalFileLineCount") .getOrCreate() // 读取本地文件 val filePath = "file:///data/bigfiles/test.txt" val lines = spark.sparkContext.textFile(filePath) // 统计行数 val lineCount = lines.count() // 将结果保存到本地文件 spark.sparkContext.parallelize(Seq(lineCount.toString)) .saveAsTextFile("file:///root/maven_result.txt") // 停止SparkSession spark.stop() } } ``` #### 2. 创建Maven项目结构 ``` spark-line-count/ ├── pom.xml └── src/ └── main/ └── scala/ └── LocalFileLineCount.scala ``` #### 3. 配置pom.xml文件 ```xml <project> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spark-line-count</artifactId> <version>1.0-SNAPSHOT</version> <properties> <spark.version>3.2.1</spark.version> <scala.version>2.12.15</scala.version> </properties> <dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.12</artifactId> <version>${spark.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>4.5.6</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> ``` #### 4. 编译打包应用程序 ```bash # 进入项目目录 cd spark-line-count # 使用Maven打包 mvn clean package ``` 打包完成后,JAR文件将生成在`target/spark-line-count-1.0-SNAPSHOT.jar` #### 5. 提交Spark应用程序 ```bash spark-submit \ --class LocalFileLineCount \ --master local[*] \ target/spark-line-count-1.0-SNAPSHOT.jar ``` #### 6. 验证结果 结果将保存在`/root/maven_result.txt`文件中: ```bash cat /root/maven_result.txt/part-* ``` #### 关键注意事项: 1. **文件路径格式**:本地文件路径需使用`file://`前缀[^2] 2. **运行模式**:使用`--master local[*]`在本地运行 3. **权限要求**:确保Spark有权限访问输入文件和输出目录 4. **结果格式**:输出为目录而非单个文件,包含part-*文件 #### 执行流程说明: 1. Spark读取本地文件`/data/bigfiles/test.txt` 2. 使用RDD的`count()`方法统计行数 3. 将结果转换为RDD并保存到本地文件 4. 输出目录包含多个part文件(取决于并行度) 通过上述步骤,您可以完成从编写代码到结果保存的完整流程[^3][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值