linux 信號_Linux信號量(1)-SYSTEM V

7ff0cf5f1ce2e72608c990c6b87ccc21.png

?

信號量概念

信號量本質上是一個計數器(不設置全局變量是因為進程間是相互獨立的,而這不一定能看到,看到也不能保證++引用計數為原子操作),用于多進程對共享數據對象的讀取,它和管道有所不同,它不以傳送數據為主要目的,它主要是用來保護共享資源(信號量也屬于臨界資源),使得資源在一個時刻只有一個進程獨享。

信號量分類

因為各種原因,Linux下有多種信號量實現機制,可以分別應用于不同的場合,分類如下:

429cabd87b4decfadde33803b51e59a7.png

用戶信號量主要運行于用戶態,比如進程間都要訪問某個文件,那么只有獲得信號量的進程才能打開文件,其他進程會進入休眠,我們也可以查看當前信號量的值,以判斷是否要進入臨界區。

內核信號量主要運行于Linux內核,主要實現對內核臨界資源的互斥使用,比如某個設備只能被某一個進程打開,無法打開設備的例程會導致用戶空間的進程休眠。

POSIX有名信號量

主要應用于線程。

 sem_t *sem_open(const char *name, int oflag, mode_t mode, int val);int sem_wait(sem_t *sem);int sem_trywait(sem_t *sem);int sem_post(sem_t *sem);int sem_close(sem_t *sem);int sem_unlink(const char *name);

每個open的位置都要close和unlink,但只有最后執行的unlink生效

POSIX無名信號量

主要應用于線程。

#include<semaphore.h>
sem_t sem;
int sem_init(sem_t *sem, int pshared, unsigned int val); //pshared為0則線程間共享,pshared為1則父子進程共享
int sem_wait(sem_t *sem); //阻塞
int sem_trywait(sem_t *sem); //非阻塞
int sem_post(sem_t *sem);
int sem_destroy(sem_t *sem);
進程間共享則sem必須放在共享內存區域(mmap, shm_open, shmget),父進程的全局變量、堆、棧中存儲是不行的

內核信號量:

#include<asm/semaphore.h>
void sema_init(struct semaphore *sem, int val);
void down(struct semaphore *sem); //可睡眠
int down_interruptible(struct semaphore *sem); //可中斷
int down_trylock(struct semaphore *sem); //m非阻塞
void up(struct semaphore *sem);

除此之外信號量還有一種分類方法

二值信號量(binary semaphore)和計數信號量(counting semaphore)。 二值信號量: 顧名思義,其值只有兩種0或1,相當于互斥量,當值為1時資源可用;而當值為0時,資源被鎖住,進程阻塞無法繼續執行。 計數信號量: 其值是在0到某個限制值之間的信號量。

信號量的工作原理

信號量只能進行兩種操作等待和發送信號,信號量操作總結起來,其核心是PV操作,P(sv)和V(sv),他們的行為是這樣的:

(1)P(sv): 如果sv的值大于零,就給它減1;如果它的值為零,就掛起該進程的執行

(2)V(sv): 如果有其他進程因等待sv而被掛起,就讓它恢復運行,如果沒有進程因等待sv而掛起,就給它加1.

在信號量進行PV操作時都為原子操作(因為它需要保護臨界資源)

注:原子操作:單指令的操作稱為原子的,單條指令的執行是不會被打斷的

System V IPC

講解System V信號量之前,先了解下什么是System V IPC。

System V IPC一共有三種類型的IPC合稱為System V IPC:

  1. System V信號量
  2. System V消息隊列
  3. System V共享內存

System V IPC在訪問它們的函數和內核為它們維護的信息上有一些類似點,主要包括:

  1. IPC鍵和ftok函數
  2. ipc_perm結構
  3. 創建或打開時指定的用戶訪問權限
  4. ipcs和ipcrm命令

下表匯總了所有System V IPC函數。

ble data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">

IPC鍵和ftok函數

三種類型的System V IPC都使用IPC鍵作為它們的標識,IPC鍵是一個key_t類型的整數,該類型在sys/types.h中定義。 IPC鍵通常是由ftok函數賦予的,該函數把一個已存在的路徑名pathname和一個非0整數id組合轉換成一個key_t值,即IPC鍵。

#include <sys/ipc.h>//成功返回IPC鍵,失敗返回-1
key_t ftok(const char *pathname, int id);

參數說明:

  • pathname在是程序運行期間必須穩定存在,不能反復創建與刪除
  • id不能為0,可以是正數或者負數

ipc_perm結構

內核給每個IPC對象維護一個信息結構,即struct ipc_perm結構,該結構及System V IPC函數經常使用的常值定義在sys/ipc.h頭文件中。

struct ipc_perm
{uid_t   uid;   //owner's user idgid_t   gid;   //owner's group iduid_t   cuid;  //creator's group idgid_t   cgid;  //creator's group idmode_t  mode;  //read-write permissionsulong_t seq;   //slot usage sequence numberkey_t   key;   //IPC key
};

創建與打開IPC對象

創建或打開一個IPC對象使用相應的xxxget函數,它們都有兩個共同的參數:

  • 參數key,key_t類型的IPC鍵
  • 參數oflag,用于指定IPC對象的讀寫權限(ipc_perm.mode),并選擇是創建一個新的IPC對象還是打開一個已存在的IPC對象

對于參數key,應用程序有兩種選擇:

  • 調用ftok,給它傳pathname和id
  • 指定key為IPC_PRIVATE,這將保證會創建一個新的、唯一的IPC對象,但該標志不能用于打開已存在的IPC對象,只能是新建

對于參數oflag,如上所述,它包含讀寫權限、創建或打開這兩方面信息:

  • 可以指定IPC_CREAT標志,其含義和Posix IPC的O_CREAT一樣
  • 還可以設置為下表所示的常值來指定讀寫權限

3ca31a229ca11aa21438fb77d6e63c0b.png

ipcs和ipcrm命令

由于System V IPC的三種類型不是以文件系統路徑名標識的,因此無法使用ls和rm命令查看與刪除它們
ipcs和ipcrm分別用于查看與刪除系統中的System V IPC
usage : ipcs -asmq -tclup ipcs [-s -m -q] -i idipcs -h for help.usage: ipcrm [ [-q msqid] [-m shmid] [-s semid][-Q msgkey] [-M shmkey] [-S semkey] ... ]

SYSTEM V 信號量

SystemV信號量并不如Posix信號量那樣“好用”,但相比之下它的年代更加久遠,但是SystemV使用的卻更加廣泛(尤其是在老系統中)。

System V信號量是指的計數信號量集(set of counting semaphores),是一個或多個信號量的集合,其中每個都是計數信號量。(注:System V 信號量是計數信號量集,Posix 信號量是單個計數信號量。)

所有函數共用頭文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

創建信號量

int semget(key_t key,int nsems,int flags)
//返回:成功返回信號集ID,出錯返回-1
  • (1)第一個參數key是長整型(唯一非零),系統建立IPC通訊 ( 消息隊列、 信號量和 共享內存) 時必須指定一個ID值。通常情況下,該id值通過ftok函數得到,由內核變成標識符,要想讓兩個進程看到同一個信號集,只需設置key值不變就可以。
  • (2)第二個參數nsem指定信號量集中需要的信號量數目,它的值幾乎總是1。
  • (3)第三個參數flag是一組標志,當想要當信號量不存在時創建一個新的信號量,可以將flag設置為IPC_CREAT與文件權限做按位或操作。 設置了IPC_CREAT標志后,即使給出的key是一個已有信號量的key,也不會產生錯誤。而IPC_CREAT | IPC_EXCL則可以創建一個新的,唯一的信號量,如果信號量已存在,返回一個錯誤。一般我們會還或上一個文件權限

刪除和初始化信號量

int semctl(int semid, int semnum, int cmd, ...);

功能: 信號量控制操作。 參數: semid標示操作的信號量集;semnum標示該信號量集內的某個成員(0,1等,直到nsems-1),semnum值僅僅用于GETVAL,SETVAL,GETNCNT,GETZCNT,GETPID,通常取值0,也就是第一個信號量;cmd:指定對單個信號量的各種操作,IPC_STAT,IPC_GETVAL,IPC_SETVAL,IPC_RMID;arg: 可選參數,取決了第三個參數cmd。 返回值: 若成功,根據cmd不同返回不同的值,IPC_STAT,IPC_SETVAL,IPC_RMID返回0,IPC_GETVAL返回信號量當前值;出錯返回-1.

如有需要第四個參數一般設置為union semnu arg;定義如下

union semun
{ int val;  //使用的值struct semid_ds *buf;  //IPC_STAT、IPC_SET 使用的緩存區unsigned short *arry;  //GETALL,、SETALL 使用的數組struct seminfo *__buf; // IPC_INFO(Linux特有) 使用的緩存區
};
  • (1)sem_id是由semget返回的信號量標識符
  • (2)semnum當前信號量集的哪一個信號量
  • (3)cmd通常是下面兩個值中的其中一個 SETVAL:用來把信號量初始化為一個已知的值。p 這個值通過union semun中的val成員設置,其作用是在信號量第一次使用前對它進行設置。 IPC_RMID:用于刪除一個已經無需繼續使用的信號量標識符,刪除的話就不需要缺省參數,只需要三個參數即可。

結構體

a3b79bc6739b01d6bbc6387879aa0d3e.png

由于system v信號量是伴隨著內核的啟動而生成,我們可以在源碼文件sem.c中看到static struct ipc_ids sem_ids;它是system v信號量的入口,因此在系統運行過程中是一直存在的。它所保存的信息是資源(在sem中是信號量集,也可以是msg,shm)的信息。如:

   struct ipc_ids {int in_use;//說明已分配的資源個數int max_id;/在使用的最大的位置索引unsigned short seq;//下一個分配的位置序列號unsigned short seq_max;//最大位置使用序列struct semaphore sem; //保護 ipc_ids的信號量struct ipc_id_ary nullentry;//如果IPC資源無法初始化,則entries字段指向偽數據結構struct ipc_id_ary* entries;//指向資源ipc_id_ary數據結構的指針};

它的最后一個元素 entries指向struct ipc_id_ary這樣一個數據結構,它有兩個成員:

 struct ipc_id_ary {int size;//保存的是數組的長度值struct kern_ipc_perm *p[0];//它是個指針數組 ,數組長度可變,內核初始化后它的值為128
};

正如我們在上圖看到的,sem_ids.entries->p指向sem_array這個數據結構,為什么呢?

我們看信號量集sem_array這個數據結構:

/* One sem_array data structure for each set of semaphores in the system. */
struct sem_array {struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */time_t   sem_otime; /* last semop time */time_t   sem_ctime; /* last change time */struct sem  *sem_base; /* ptr to first semaphore in array */指向信號量隊列struct sem_queue *sem_pending; /* pending operations to be processed */指向掛起隊列的首部struct sem_queue **sem_pending_last; /* last pending operation */指向掛起隊列的尾部struct sem_undo  *undo;  /* undo requests on this array */信號量集上的 取消請求unsigned long  sem_nsems; /* no. of semaphores in array */信號量集中的信號量的個數
};

這樣sem_ids.entries就跟信號量集sem_array關聯起來了,但是為什么要通過kern_ipc_perm關聯呢,為什么不直接由sem_ids指向sem_array呢,這是因為信號量,消息隊列,共享內存實現的機制基本差不多,所以他們都是通過ipc_id_ary這個數據結構管理,而通過kern_ipc_perm,他們與各自的數據結構關聯起來。這樣就清楚了!在后面我們來看內核函數sys_semget()是如何進行創建信號量集,并將其加入到sem_ids.entries中的。

改變信號量的值

int semop(int semid, struct sembuf *sops, size_t nops);

功能: 操作信號量,P,V 操作

參數: semid:信號量集標識符;nops是opstr數組中元素數目,通常取值為1;opstr指向一個結構數組 nsops:進行操作信號量的個數,即sops結構變量的個數,需大于或等于1。最常見設置此值等于1,只完成對一個信號量的操作 sembuf的定義如下:

struct sembuf{ short sem_num;   //除非使用一組信號量,否則它為0 short sem_op; //信號量在一次操作中需要改變的數據,通   //常是兩個數,一個是-1,即P(等待)操作, //一個是+1,即V(發送信號)操作。 short sem_flg; //通常為SEM_UNDO,使操作系統跟蹤 //信號量,并在進程沒有釋放該信號量而終止時,操作系統釋放信號量 
};

返回值: 成功返回信號量標識符,出錯返回-1

一般編程步驟:

  1. 創建信號量或獲得在系統中已存在的信號量 1). 調用semget(). 2). 不同進程使用同一個信號量鍵值來獲得同個信號量
  2. 初始化信號量 1).使用semctl()函數的SETVAL操作 2).當使用二維信號量時,通常將信號量初始化為1
  3. 進行信號量PV操作 1). 調用semop()函數 2). 實現進程之間的同步和互斥
  4. 如果不需要該信號量,從系統中刪除 1).使用semctl()函數的IPC_RMID操作

實例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#define USE_SYSTEMV_SEM 1
#define DELAY_TIME 2
union semun {int val;struct semid_ds *buf;unsigned short *array;
};
// 將信號量sem_id設置為init_value
int init_sem(int sem_id,int init_value) {union semun sem_union;sem_union.val=init_value;if (semctl(sem_id,0,SETVAL,sem_union)==-1) {perror("Sem init");exit(1);}return 0;
}
// 刪除sem_id信號量
int del_sem(int sem_id) {union semun sem_union;if (semctl(sem_id,0,IPC_RMID,sem_union)==-1) {perror("Sem delete");exit(1);}return 0;
}
// 對sem_id執行p操作
int sem_p(int sem_id) {struct sembuf sem_buf;sem_buf.sem_num=0;//信號量編號sem_buf.sem_op=-1;//P操作sem_buf.sem_flg=SEM_UNDO;//系統退出前未釋放信號量,系統自動釋放if (semop(sem_id,&sem_buf,1)==-1) {perror("Sem P operation");exit(1);}return 0;
}
// 對sem_id執行V操作
int sem_v(int sem_id) {struct sembuf sem_buf;sem_buf.sem_num=0;sem_buf.sem_op=1;//V操作sem_buf.sem_flg=SEM_UNDO;if (semop(sem_id,&sem_buf,1)==-1) {perror("Sem V operation");exit(1);}return 0;
}
int main() {pid_t pid;
#if USE_SYSTEMV_SEMint sem_id;key_t sem_key;sem_key=ftok(".",'A');printf("sem_key=%xn",sem_key);//以0666且create mode創建一個信號量,返回給sem_idsem_id=semget(sem_key,1,0666|IPC_CREAT);printf("sem_id=%xn",sem_id);//將sem_id設為1init_sem(sem_id,1);
#endifif ((pid=fork())<0) {perror("Fork error!n");exit(1);} else if (pid==0) {
#if USE_SYSTEMV_SEMsem_p(sem_id); //    P操作
#endifprintf("Child running...n");sleep(DELAY_TIME);printf("Child %d,returned value:%d.n",getpid(),pid);
#if USE_SYSTEMV_SEMsem_v(sem_id); //    V操作
#endifexit(0);} else {
#if USE_SYSTEMV_SEMsem_p(sem_id); //    P操作
#endifprintf("Parent running!n");sleep(DELAY_TIME);printf("Parent %d,returned value:%d.n",getpid(),pid);
#if USE_SYSTEMV_SEMsem_v(sem_id); //    V操作waitpid(pid,0,0);del_sem(sem_id);
#endifexit(0);}
}

運行結果如下:

b77389ad023dec2ce66790cf9e0e16a2.png

獲取更多關于Linux的資料,請關注公眾號「一口Linux」

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534136.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kali linux 截圖位置,Kali Linux中使用shutter截圖工具 | CN-SEC 中文網

摘要在Kali 2017以前的版本中默認有一款截圖工具--screenshot&#xff0c;升級到2017版后找不到了&#xff0c;下面介紹一款同樣好用的截圖工具---shutter在Kali 2017以前的版本中默認有一款截圖工具--screenshot&#xff0c;升級到2017版后找不到了&#xff0c;下面介紹一款同…

python畫圖庫哪個好_機器學習基礎5--python畫圖庫matplotlib(上)

圖像是我們最直觀的數據表達方式&#xff0c;python的matplotlib庫可以用來畫圖。下面來簡單總結下matplotlib的使用方法。上篇講matplot畫圖中用到的基礎對象&#xff0c;包括圖像Figure&#xff0c;平面曲線Line2D&#xff0c;坐標軸Axes&#xff0c;圖例Legend, 注解Annotat…

64位 linux 32位連接器,32位匯編程序在64位Ubuntu上的匯編和連接

本教程使用的操作系統是Ubuntu Linux 18.04 LTS版本&#xff0c;匯編器是GNU AS(簡稱as)&#xff0c;連接器是GNU LD(簡稱ld)。以下是一段用于檢測CPU品牌的匯編小程序(cpuid2.s)&#xff1a;.section .dataoutput:.asciz "The processor Vendor ID is %s\n".section…

python怎么加圖片_python中如何保存圖片

一提到數字圖像處理&#xff0c;可能大多數人就會想到matlab&#xff0c;但matlab也有自身的缺點&#xff1a; 1、不開源&#xff0c;價格貴 2、軟件容量大。一般3G以上&#xff0c;高版本甚至達5G以上。 3、只能做研究&#xff0c;不易轉化成軟件。python學習網&#xff0c;大…

linux用rsync實現同步,Linux下使用rsync實現主備機代碼同步

rsync 分為客戶端和服務端軟件版本&#xff1a;rsync-2.6.9軟件下載地址&#xff1a;http://rsync.samba.org/ftp/rsync/服務端安裝過程1.tar -xzvf rsync-2.6.9.tar.gz #解壓縮安裝文件2.cd rsync-2.6.93. ./configure --prefix/usr/local/rsync #配置安裝目錄為/usr/local/…

python可以在多平臺運行 體現了_Python:使用異常處理來判斷運行的平臺

try:importtermios, TERMIOS               1exceptImportError:try:importmsvcrt                  2exceptImportError:try:from EasyDialogs importAskPassword   3exceptImportError: getpass "default_getpass"      …

python精通時間_學Python需要多久能學會?精通Python需要多長時間?

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓 嚴格意思上的說&#xff0c;Python其實是一個腳本語言&#xff0c;編程語言多種多樣&#xff0c;但是卻有開源和閉源之分&#xff0c;Python就是一種開放核心源代碼編程語言&#xff0c;其開發代碼的效率非常高&#xff0c;代碼編…

linux 文檔編輯器 word,linux下vi編輯器命令大全

常用命令linux下vi編輯器命令大全來源&#xff1a;考試大 【學而優則進&#xff0c;考試大以成&#xff01;】 2007年8月14日  文本編輯器是所有計算機系統中最常用的一種工具。UNIX下的編輯器有ex,sed和vi等&#xff0c;其中&#xff0c;使用最為廣泛的是vi&#xff0c;而vi…

西門子觸摸屏修改ip地址_基于博途V15 西門子S7-1200與觸摸屏一個簡單的例子

本篇是《基于博途V15 西門子S7-1200 ...》系列的后續篇&#xff0c;看懂本篇文章之前請大家關注我&#xff0c;然后查找相關文章&#xff0c;學習之后再學習此篇。也請專業領域的大神批評指正。感謝大家關注與支持&#xff01;步驟&#xff1a;1. 創建項目創建名稱為PLC_HMI2. …

mac os和linux和安卓,在我的安卓手機里,安裝Windows和macOS系統

原標題&#xff1a;在我的安卓手機里&#xff0c;安裝Windows和macOS系統不知道各位差友還記不記得&#xff0c;世超前陣子分享過一款無需越獄&#xff0c;就能讓 iPhone 和 iPad 運行其它系統的虛擬機軟件 UTM。當時世超正是靠著這個軟件&#xff0c;才得以讓 iPad 成功跑上了…

python連接mysql代碼_Python3連接MySQL(pymysql)轉賬代碼

# coding:utf8 import sys # Python3 采用pymysql 連接MySQL import pymysql class TransferMoney(object): def __init__(self,conn): self.connconn def check_acct_available(self,acctid): cursor self.conn.cursor() try: sql"select * from account where acctid%s…

gc java root_C#技術漫談之垃圾回收機制(GC)

GC的前世與今生雖然本文是以.NET作為目標來講述GC&#xff0c;但是GC的概念并非才誕生不久。早在1958年&#xff0c;由鼎鼎大名的圖林獎得主John McCarthy所實現的Lisp語言就已經提供了GC的功能&#xff0c;這是GC的第一次出現。Lisp的程序員認為內存管理太重要了&#xff0c;所…

中信銀行c語言筆試題庫,中信銀行筆試題型及題目

中信銀行筆試題型及題目考試題型一&#xff1a;專業知識(2個小時)1.專業知識單選&#xff0c;60題&#xff0c;每題1分。2.專業知識多選&#xff0c;20題&#xff0c;每題1分&#xff0c;未選全即少選得0.5分&#xff0c;錯選、漏選得0分。3.英語閱讀&#xff0c;20分&#xff…

北航軟件工程碩士_21考研擇校 | 北京航空航天大學軟件工程怎么樣?

??? 軟件工程考研獨家平臺撰稿 | 康康哥編輯 | 麗麗姐本文由懂計算機、軟件工程的博士師哥原創01學校名氣北京航空航天大學&#xff0c;簡稱“北航”&#xff0c;是一所把“985”、“211”、“雙一流”寫進骨子里的學校。為什么這么說呢&#xff1f;這得從源頭說起&#xff…

kettle同步數據到hive 巨慢_超詳細教程,kettle ETL mysql到hadoop hive數據抽取,值得收藏...

那么如何將mysql數據導入到hive里呢&#xff0c;kettle里有自帶方法&#xff0c;可以通過表輸入和表輸出來實現&#xff0c;不過自帶的方法載入數據極其緩慢&#xff0c;不推薦使用這種方法。1、hive建表注意hive表使用“^”作為分隔符&#xff0c;這個可以更具實際情況來。2、…

linux 查看path文件,linux入門之環境變量與文件查找

環境變量分類當前 Shell 進程私有用戶自定義變量&#xff0c;如上面我們創建的 temp 變量&#xff0c;只在當前 Shell 中有效。Shell 本身內建的變量。從自定義變量導出的環境變量。declare tmp;tmp"shiyanlou i love y";echo $tmp &#xff1b; **不要忘記$**實驗樓…

python手機編譯器可以干什么_世界上最好的Python編輯器是什么?

在這種情況下&#xff0c;你需要使用一個 IDE&#xff08;集成開發環境&#xff09;或專用的代碼編輯器。由于 Python 是最流行的編程語言之一&#xff0c;IDE 的選擇也非常多。那么問題來了&#xff1a;「究竟什么樣的 IDE 最適合 Python&#xff1f;」 很明顯&#xff0c;沒有…

c是過程化語言嗎數據庫,A.數據庫語言B.過程化語言C.宿主語言D.數據庫管理系統...

A&#xff0e;數據庫語言B&#xff0e;過程化語言C&#xff0e;宿主語言D&#xff0e;數據庫管理系統更多相關問題[填空題] 為了安全起見&#xff0c;起動發動機前要檢查()有無行人。---叉車操作和保養手冊第2-77.在起動叉車前()以警告周圍的人。[單選] 制造廠規定叉車走合期一…

python讀取xlsx文件pandas_用Python的pandas框架操作Excel文件中的數據教程

引言 本文的目的&#xff0c;是向您展示如何使用pandas來執行一些常見的Excel任務。有些例子比較瑣碎&#xff0c;但我覺得展示這些簡單的東西與那些你可以在其他地方找到的復雜功能同等重要。作為額外的福利&#xff0c;我將會進行一些模糊字符串匹配&#xff0c;以此來展示一…

delphi 生成 超大量xml_用OpenCV4實現圖像的超分別率

用OpenCV4實現圖像的超分別率本實驗原文鏈接&#xff1a; f"https://arxiv.org/pdf/1807.06779.pdf">https://arxiv.org/pdf/1807.06779.pdf原文摘要單圖像超分辨率&#xff08;SISR&#xff09;的主要挑戰是如何恢復微小紋理等高頻細節。然而&#xff0c;大多數最…