This commit is contained in:
2026-06-09 06:43:13 +02:00
parent 43902c20e4
commit 2f42b036a9
33 changed files with 2077 additions and 40 deletions

View File

@@ -0,0 +1,327 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from docx import Document
from docx.shared import Pt, Inches, Cm, Twips
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
def set_cell_border(cell, **kwargs):
"""Set cell borders"""
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
tcBorders = OxmlElement('w:tcBorders')
for edge in ('top', 'left', 'bottom', 'right'):
if edge in kwargs:
element = OxmlElement(f'w:{edge}')
element.set(qn('w:val'), kwargs[edge].get('val', 'single'))
element.set(qn('w:sz'), str(kwargs[edge].get('sz', 4)))
element.set(qn('w:color'), kwargs[edge].get('color', '000000'))
tcBorders.append(element)
tcPr.append(tcBorders)
def create_paragraph(doc, text, font_size=12, bold=False, alignment=WD_ALIGN_PARAGRAPH.LEFT, first_line_chars=0, first_line=0):
"""Create a paragraph with specified formatting"""
p = doc.add_paragraph()
p.alignment = alignment
# Set paragraph spacing
p.paragraph_format.line_spacing = Pt(18)
if first_line_chars > 0:
p.paragraph_format.first_line_chars = first_line_chars
if first_line > 0:
p.paragraph_format.first_line_indent = Pt(first_line)
run = p.add_run(text)
run.font.size = Pt(font_size)
run.font.bold = bold
run.font.name = '宋体'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
return p
def create_heading(doc, text, level=1):
"""Create a section heading"""
p = doc.add_paragraph()
p.paragraph_format.line_spacing = Pt(18)
p.paragraph_format.space_before = Pt(12 if level == 1 else 6)
p.paragraph_format.space_after = Pt(6 if level == 1 else 3)
run = p.add_run(text)
run.font.size = Pt(14 if level == 1 else 12)
run.font.bold = True
run.font.name = '宋体'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
return p
def create_code_paragraph(doc, text):
"""Create a paragraph with monospace font for code"""
p = doc.add_paragraph()
p.paragraph_format.line_spacing = Pt(14)
p.paragraph_format.first_line_indent = Pt(0)
run = p.add_run(text)
run.font.size = Pt(10)
run.font.name = 'Courier New'
return p
# Create document
doc = Document()
# Set page margins
sections = doc.sections
for section in sections:
section.top_margin = Inches(0.8)
section.bottom_margin = Inches(0.8)
section.left_margin = Inches(0.4)
section.right_margin = Inches(0.4)
# Title
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run("网络空间安全学院")
run.font.size = Pt(16)
run.font.bold = True
run.font.name = '华文中宋'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '华文中宋')
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run("实验报告(电子版)")
run.font.size = Pt(16)
run.font.bold = True
run.font.name = '华文中宋'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '华文中宋')
doc.add_paragraph()
# Info table
table = doc.add_table(rows=3, cols=6)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# Row 1: Experiment name
row = table.rows[0]
row.cells[0].text = "实验名称"
row.cells[1].merge(row.cells[2]).merge(row.cells[3])
row.cells[1].text = "Linux多线程编程"
row.cells[4].text = "指导教师"
row.cells[5].text = ""
# Row 2: Name, ID, Class
row = table.rows[1]
row.cells[0].text = "姓 名"
row.cells[1].text = "吕锦中"
row.cells[2].text = "学 号"
row.cells[3].text = "2024414290124"
row.cells[4].text = "班 级"
row.cells[5].text = "软件工程一班"
# Row 3: Location, Date, Group
row = table.rows[2]
row.cells[0].text = "实验地点"
row.cells[1].text = ""
row.cells[2].text = "实验日期"
row.cells[3].text = ""
row.cells[4].text = "同组同学"
row.cells[5].text = ""
# Format table cells
for row in table.rows:
for cell in row.cells:
for p in cell.paragraphs:
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
for run in p.runs:
run.font.size = Pt(12)
doc.add_paragraph()
# Section 1: 实验目的
create_heading(doc, "一、实验目的:")
create_paragraph(doc, "1. 通过编程训练,掌握多线程编程、线程间互斥/同步编程基本方法;")
create_paragraph(doc, "2. 通过应用编程,掌握多线程并行程序设计与性能分析方法;")
create_paragraph(doc, "3. 编写进程管理和线程管理函数测时程序,巩固测试函数应用编程,通过用时比较,建立进程和线程管理性能概念;")
create_paragraph(doc, "4. 编写动态线程管理程序,建立负载均衡管理的初步概念。")
doc.add_paragraph()
# Section 2: 实验内容
create_heading(doc, "二、实验内容:")
create_paragraph(doc, "任务1必做编写程序task61.c主线程创建3个对等线程T1、T2、T3每个线程利用循环执行5次printf输出操作两次循环间随机等待1-5s时间。主线程等待所有对等线程结束后终止进程。")
create_paragraph(doc, "任务2必做编译、测试和运行badcount.c程序用信号量方法改写程序实现对共享变量的安全访问。")
create_paragraph(doc, "任务3必做编写多线程生产者/消费者程序task63.c使用信号量实现同步。")
create_paragraph(doc, "任务4必做编译、测试和运行psum64.c实现并行计算平方和。")
create_paragraph(doc, "任务5选做编写矩阵乘法并行程序matmult.c并验证正确性。")
create_paragraph(doc, "任务6任选测量fork()与pthread_create()函数调用开销。")
create_paragraph(doc, "任务7任选编写动态线程池管理程序task67.c。")
doc.add_paragraph()
# Section 3: 相关情况介绍
create_heading(doc, "三、相关情况介绍")
create_paragraph(doc, "本实验使用Linux系统提供的POSIX线程库pthread进行多线程编程。实验中涉及线程创建、线程同步信号量、互斥锁、条件变量等概念。通过多个实际任务涵盖了多线程编程的主要方面。")
doc.add_paragraph()
# Section 4: 报告内容
create_heading(doc, "四、报告内容")
# Task 1
create_heading(doc, "任务1多线程创建与基本同步", level=2)
create_heading(doc, "1. 设计思想", level=2)
create_paragraph(doc, "本程序创建三个对等线程T1、T2、T3每个线程执行不同的输出任务。主线程使用pthread_join()等待所有对等线程结束。")
create_heading(doc, "2. 源代码", level=2)
create_paragraph(doc, "#include <pthread.h>")
create_paragraph(doc, "#include <time.h>")
create_paragraph(doc, "// 完整源代码见task61.c")
create_heading(doc, "3. 编译过程", level=2)
create_paragraph(doc, "gcc -o task61 task61.c -lpthread")
create_heading(doc, "4. 测试数据", level=2)
create_paragraph(doc, "程序无输入参数,直接运行。")
create_heading(doc, "5. 运行结果", level=2)
create_paragraph(doc, "My name is Lvjinzhong")
create_paragraph(doc, "My student number is 2024414290124")
create_paragraph(doc, "Current time Fri May 29 11:32:12 2026")
doc.add_paragraph()
# Task 2
create_heading(doc, "任务2信号量实现互斥访问", level=2)
create_heading(doc, "1. 设计思想", level=2)
create_paragraph(doc, "原badcount.c程序存在竞态条件多个线程同时对共享变量cnt进行增减操作导致结果不正确。本程序使用二元信号量mutex实现对cnt变量的互斥访问保护。")
create_heading(doc, "2. 源代码(核心部分)", level=2)
create_paragraph(doc, "sem_t mutex;")
create_paragraph(doc, "sem_init(&mutex, 0, 1);")
create_paragraph(doc, "// 在increase/decrease函数中")
create_paragraph(doc, "sem_wait(&mutex); cnt++; sem_post(&mutex);")
create_heading(doc, "3. 编译过程", level=2)
create_paragraph(doc, "gcc -o task62 task62.c -lpthread")
create_heading(doc, "4. 测试数据", level=2)
create_paragraph(doc, "运行时指定迭代次数,如:./task62 100000")
create_heading(doc, "5. 运行结果", level=2)
create_paragraph(doc, "Correct! cnt=0")
doc.add_paragraph()
# Task 3
create_heading(doc, "任务3生产者-消费者问题", level=2)
create_heading(doc, "1. 设计思想", level=2)
create_paragraph(doc, "使用有界缓冲区实现生产者-消费者同步。slots信号量表示缓冲区空槽数items信号量表示缓冲区产品数mutex保护缓冲区的临界区操作。")
create_heading(doc, "2. 源代码(核心数据结构)", level=2)
create_paragraph(doc, "typedef struct {")
create_paragraph(doc, " int *buf; int n; int inpos, outpos;")
create_paragraph(doc, " sem_t mutex, slots, items;")
create_paragraph(doc, "} sbuf_t;")
create_heading(doc, "3. 编译过程", level=2)
create_paragraph(doc, "gcc -o task63 task63.c -lpthread")
create_heading(doc, "4. 测试数据", level=2)
create_paragraph(doc, "./task63 2 3 5 表示2个生产者、3个消费者、缓冲区大小为5")
create_heading(doc, "5. 运行结果", level=2)
create_paragraph(doc, "Produced sum: 2765")
create_paragraph(doc, "Consumed sum: 2765")
create_paragraph(doc, "Verification successful")
doc.add_paragraph()
# Task 4
create_heading(doc, "任务4并行计算平方和", level=2)
create_heading(doc, "1. 设计思想", level=2)
create_paragraph(doc, "将0到n-1的平方和分配给多个线程并行计算。每个线程计算自己分配区间的平方和最后将各线程的结果求和。")
create_heading(doc, "2. 源代码(核心部分)", level=2)
create_paragraph(doc, "void *sum(void *vargp) {")
create_paragraph(doc, " unsigned long long begin = myid * nelems_per_thread;")
create_paragraph(doc, " for (i = begin; i < end; i++) lsum += i * i;")
create_paragraph(doc, "}")
create_heading(doc, "3. 编译过程", level=2)
create_paragraph(doc, "gcc -o task64 task64.c -lpthread")
create_heading(doc, "4. 测试数据与结果", level=2)
create_paragraph(doc, "Threads=1: Time=0.001945s, result=549755289600")
create_paragraph(doc, "Threads=2: Time=0.001522s")
create_paragraph(doc, "Threads=4: Time=0.001612s")
create_paragraph(doc, "Threads=8: Time=0.001587s")
create_paragraph(doc, "Threads=16: Time=0.002894s")
doc.add_paragraph()
# Task 5
create_heading(doc, "任务5矩阵乘法并行化", level=2)
create_heading(doc, "1. 设计思想", level=2)
create_paragraph(doc, "将N×N矩阵按行分配给多个线程并行计算。每个线程计算其负责的行与其他列的乘积最后汇总结果。")
create_heading(doc, "2. 源代码(核心部分)", level=2)
create_paragraph(doc, "for (i = start_row; i < end_row; i++)")
create_paragraph(doc, " for (j = 0; j < N; j++)")
create_paragraph(doc, " C[i][j] = sum(A[i][k] * B[k][j]);")
create_heading(doc, "3. 编译过程", level=2)
create_paragraph(doc, "gcc -o matmult matmult.c -lpthread")
create_heading(doc, "4. 测试数据与结果N=128, 4线程", level=2)
create_paragraph(doc, "Serial time: 0.010762s")
create_paragraph(doc, "Parallel time: 0.004444s")
create_paragraph(doc, "Speedup: 2.42, Efficiency: 0.605")
doc.add_paragraph()
# Task 6
create_heading(doc, "任务6进程与线程创建开销比较", level=2)
create_heading(doc, "1. 设计思想", level=2)
create_paragraph(doc, "通过反复调用fork()和pthread_create()各1000次计算平均每次调用的执行时间。fork需要复制进程资源而pthread_create只创建轻量级线程。")
create_heading(doc, "2. 源代码(核心部分)", level=2)
create_paragraph(doc, "// fork测量")
create_paragraph(doc, "pid_t pid = fork(); if(pid==0) _exit(0); waitpid(pid,NULL,0);")
create_paragraph(doc, "// pthread_create测量")
create_paragraph(doc, "pthread_create(&tid, NULL, func, NULL); pthread_join(tid, NULL);")
create_heading(doc, "3. 编译过程", level=2)
create_paragraph(doc, "gcc -o task66 task66.c -lpthread")
create_heading(doc, "4. 运行结果", level=2)
create_paragraph(doc, "pthread_create() + pthread_join(): 0.178 ms")
create_paragraph(doc, "fork() + waitpid(): 0.549 ms")
create_paragraph(doc, "fork比pthread_create慢约3倍")
doc.add_paragraph()
# Task 7
create_heading(doc, "任务7动态线程池管理", level=2)
create_heading(doc, "1. 设计思想", level=2)
create_paragraph(doc, "主线程预先创建工作线程,通过有界缓冲区接收任务。当缓冲区满时,工作线程数翻倍;当缓冲区空时,工作线程数减半。")
create_heading(doc, "2. 源代码(核心部分)", level=2)
create_paragraph(doc, "void *worker(void *arg) {")
create_paragraph(doc, " while(1) { task = sbuf_remove(&buf); sleep(task); }")
create_paragraph(doc, "}")
create_heading(doc, "3. 编译过程", level=2)
create_paragraph(doc, "gcc -o task67 task67.c -lpthread")
create_heading(doc, "4. 测试数据", level=2)
create_paragraph(doc, "运行后输入命令10 5 表示创建10个任务每个任务执行5秒")
create_heading(doc, "5. 运行结果", level=2)
create_paragraph(doc, "Dynamic Thread Pool")
create_paragraph(doc, "Buffer size: 20, Initial threads: 5")
create_paragraph(doc, "> 10 5")
create_paragraph(doc, "[Worker 0] executing task: sleep 5 seconds")
doc.add_paragraph()
# Section 5: 实验分析与总结
create_heading(doc, "五、实验分析与总结")
create_heading(doc, "任务2分析互斥锁的正确性", level=2)
create_paragraph(doc, "原badcount.c程序存在严重的竞态条件。当多个线程同时执行cnt++和cnt--时操作不是原子的可能导致计数错误。使用信号量实现互斥访问后确保了同一时刻只有一个线程能修改共享变量程序输出cnt=0说明同步机制正确有效。")
create_heading(doc, "任务3分析生产者-消费者同步", level=2)
create_paragraph(doc, "本程序使用三个信号量实现完整同步slots计数空槽数items计数产品数mutex保护缓冲区。验证方案通过比较生产者产生的随机数之和与消费者接收的随机数之和来验证正确性。实验结果显示两者相等证明同步机制工作正常。")
create_heading(doc, "任务4分析并行计算加速比", level=2)
create_paragraph(doc, "从测试结果看线程数从1增加到2时执行时间从0.001945s降至0.001522s有明显加速。但线程数继续增加时加速效果不明显甚至在16线程时时间增加。这说明对于该计算任务存在以下问题1任务粒度太小线程创建和同步开销占比大2缓存争用导致性能下降3实际并行度受CPU核心数限制。")
create_heading(doc, "任务5分析矩阵乘法并行效率", level=2)
create_paragraph(doc, "N=128的矩阵乘法使用4线程获得了2.42的加速比效率为0.605。这说明并行化有一定效果,但由于矩阵不大,线程通信和同步开销仍占一定比例。随着矩阵规模增大和线程数增加,效率会进一步提升。")
create_heading(doc, "任务6分析进程与线程创建开销", level=2)
create_paragraph(doc, "fork()创建进程需要复制整个进程空间包括内存描述符、文件描述符等资源而pthread_create()只需创建一个轻量级线程共享进程资源。实验结果显示fork()的开销约为pthread_create()的3倍符合理论预期。")
create_heading(doc, "任务7分析动态线程池", level=2)
create_paragraph(doc, "动态线程池通过根据负载动态调整工作线程数来提高资源利用率。缓冲区满时增加线程,缓冲区空时减少线程。但实际测试中发现线程数调整可能导致任务重新分配的问题,需要更精细的同步机制。")
create_heading(doc, "总结", level=2)
create_paragraph(doc, "本次实验系统地练习了Linux多线程编程的各个方面包括线程创建与同步、互斥访问、生产者-消费者问题、并行计算性能分析等。通过实际编程和测试,加深了对线程同步机制和并行程序性能特征的理解。")
# Save document
output_path = "/home/cho/C/C-exp-collection/exp1/Linux多线程编程实验(2)_completed.docx"
doc.save(output_path)
print(f"Document saved to: {output_path}")