導航:首頁 > 網路營銷 > semopen許可權位

semopen許可權位

發布時間:2020-08-20 01:22:57

1、如何操作 Office Open XML 格式文檔

創建一個Office Open XML格式文件
此部分中,您將檢測一個包含文本,圖像和屬性的示例Word 2007文檔的XML文件格式。
在Word中創建一個Office Open XML 格式文檔

1.

啟動 Word 2007。

2.

在新建文檔中,粘貼以下文本:
Soaring with the American Bald Eagle
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla rutrum. Phasellus feugiat bibenm urna. Aliquam lacinia diam ac felis. In vulputate semper orci. Quisque blandit. Mauris et nibh. Aenean nulla. Mauris placerat tempor libero.
Pellentesque bibenm. In consequat, sem molestie iaculis venenatis, orci nunc imperdiet justo, id ultricies ligula elit sit amet ante. Sed quis sem. Ut accumsan nulla vel nisi. Ut nulla enim, ullamcorper vel, semper vitae, vulputate vel, mi. Duis id magna a magna commodo interm.

3.

高亮顯示Soaring with the American Bald Eagle,然後在 開始標簽,在樣式組中,設置樣式為標題。

4.

下一步,在文檔中插入一張圖片:

1.

將滑鼠指針放置在第一段落的末尾,並且點擊回車插入新行。

2.

然後,點擊插入標簽,點擊圖片,找到一個圖片文件 (例如包含在下載中的Eagle1.gif文件),然後點擊插入。

5.

現在添加一個文檔屬性:

1.

點擊Microsoft Office按鈕,指向准備,然後點擊屬性 。

2.

在文檔屬性面板中,添加作者名稱,標題,主題和備注,類似於以下:

表1.文檔屬性設置
屬性 描述

作者

Nancy Davolio

標題

Soaring with the American Bald Eagle

主題

Bald Eagles

備注

A study of the bald eagle

6.

下一步,在文檔中添加一些批註

1.

在審閱標簽下,點擊新建批註。

2.

在批註框中,輸入This is my comment。此時您的文檔類似於圖1。

圖1. 示例Office Word 2007 文檔

7.

下一步,保存文檔:

1.

點擊Microsoft Office 按鈕,然後點擊另存為。

2.

在另存為文件類型列表中,選擇 Word Document (*.docx),然後在文件名稱框中輸入SampleWordDocument.docx。

3.

點擊保存。

8.

關閉Word。

返回頁首

瀏覽Office Open XML格式文件
在此部分中,您將瀏覽您剛剛創建的示例文檔。
瀏覽Office Open XML 格式文檔

1.

打開Windows資源管理器。

2.

找到 SampleWordDocument.docx文件,右鍵點擊此文件,然後選擇重命名。
重要:
使用下面的三個步驟來抽取Office Open XML格式文件。根據您使用的操作系統不同(Windows XP或Windows Vista),第5步有所不同。

3.

在文件名稱後面添加一個.zip擴展名,文件名稱現在變為 SampleWordDocument.docx.zip。

4.

當彈出警告信息時,點擊確定。

5.

抽取容器文件:

1.

(如果您使用Windows XP:) 右鍵點擊SampleWordDocument.docx.zip文件,指向打開方式,然後點擊Compressed (zipped) Folders。此時組成文檔的文件夾和部件將會顯示在資源管理器中。

2.

(如 果您使用Windows Vista:) 右鍵點擊SampleWordDocument.docx.zip 文件,然後點擊Extract All。 在Extract Compressed (Zipped) Folders 對話框中,接受默認位置或者選擇一個新的位置,然後點擊Extract。此時組成文檔的文件夾和部件將會顯示在資源管理器中。

在下面的步驟中,您將檢測包含在文檔中的關鍵部件。

6.

檢測 [Content_Types].xml部件:

1.

使用Windows資源管理器,找到名為[Content_Types].xml的文件。

2.

右 鍵點擊此文件,指向打開方式,然後點擊Internet Explorer。每一個Office Open XML格式文檔的根下都有一個 [Content_Types].xml 組件。 [Content_Types].xml組件的作用就是確定文檔中每個唯一類型組件。每個組件需要在這個組件中列出它自己的類型。組件需要有可以識別的類 型,以便應用程序知道當渲染此文檔時如何使用這個組件。類型也能夠使您了解到組件的作用以及如何使用。

3.

關閉文件。

7.

檢測.rels 文件夾:
關 聯代表著兩個組件之間的連接。關聯是存儲在_rels子文件夾中的組件。任何組件都有相關聯的組件,包含在同結構的_rels文件夾中,此文件夾包含了一 個定義它們關系的.rels組件。子文件夾創建在與組件相同的文件夾下。一個關聯的名稱通過在原始組件的文件名後加上.rels擴展名獲得 (用於文檔文件的關聯組件是一個例外;它的名稱為「.rels」)。

1.

在Windows資源管理器中,雙擊_rels 文件夾,然後右鍵點擊.rels 文件。

2.

指向打開方式,點擊選擇程序,點擊Internet Explorer,然後點擊確定。

3.

完成檢測後,關閉IE。

8.

檢測docProps 文件夾:
2007版本中的文檔屬性在三個Microsoft Office System程序中是始終保持結構化的。分成三個邏輯XML組件,它們被存儲自docProps子文件夾下。這使得用戶可以很容易的進行訪問,因為他們它們在相同的位置並且不會和其它的文檔內容混淆。
在Windows資源管理器中,雙擊docProps 文件夾,右鍵點擊core.xml 文件,指向打開方式,然後點擊Internet Explorer。

9.

檢測core.xml 組件:
打開 core.xml 組件,然後觀察顯示的您之前輸入的屬性。 core.xml組件持有用戶輸入的用來標識文檔的屬性,例如標題,主題和作者。

10.

檢測custom.xml 組件:
從Windows資源管理器中,在Internet Explorer中打開custom.xml。
custom.xml 組件包含了被用戶,開發人員或者通過自定義邏輯添加到文檔任何自定義文檔屬性。

11.

檢測app.xml 組件:
從Windows 資源管理器中,在Internet Explorer中打開 app.xml。
app.xml 組件包括在應用程序級別指定到文檔的唯一屬性,例如文章的頁數,文本行的數量,應用程序的版本等等。

12.

檢測word文件夾:
大部分的內容組件都駐留在word子文件夾下面。另外,在裡面也有一個_rels關聯子文件夾。
雙擊 _rels 文件夾。
在_rels 子文件夾中,用於連接所有文檔組件的關聯名稱為document.xml.rels。

13.

檢測document.xml.rels 組件:
在Internet Explorer中打開document.xml.rels 。
關聯使用IDs和Uniform Resource Identifiers (URIs)來定位組件。它允許在沒有任何硬編碼引用的前提下所有非關聯的組件是無效的。在後面的章節中將會詳細討論。
在Word文件夾下面,注意styles.xml 組件。

14.

檢測styles.xml組件:
在Internet Explorer中 styles.xml。
這個包含了一些可用的重音和底紋,您可以在文檔中使用它們。

15.

必須的和可選的組件

16.

在Office Open XML格式文件中這些組件的使用使得文檔能夠以高度模塊化的方式存儲。一些組件對文檔來說是必須有效的,例如document.xml組件和fontTable.xml組件。

17.

檢測document.xml 組件:

1.

在Internet Eexplorer中打開document.xml 。 document.xml 組件包含了文檔主體的文本。

2.

查看完此文件後,關閉Internet Explorer。

18.

檢測fontTable.xml 組件:

1.

在Internet Explorer中打開fontTable.xml組件。
fontTable.xml組件包含了文檔的字體設置。

2.

查看完此文件後,關閉Internet Explorer。
如果組件描述的功能在文檔中使用不到的話,這些組件就不是必需的。示例中包括了備注,頁眉組件和頁腳組件,這些組件對Word文檔來說是可選的。這就使得用戶能夠輕松的通過文檔結構進行操縱,而不需要研究沒有使用的內容。
XML 設計用於結構化的內容,並不會本地支持二進制的內容,例如圖像或者OLE對象。二進制數據能夠被編碼到字元並且以XML形式進行存儲,但是它需要一個編碼 和解碼的過程,這就使得對於應用程序或者開發人員來說效率低下。在2007發布之後,此時就不在需要編碼二進制對象因為他們能夠作為二進制組件以他們自身 的格式進行存儲。因此在Office文檔中訪問二進制對象變得非常容易。媒體文件存儲在media文件夾中。

19.

檢測word"media和word"embeddings文件夾:
在Windows資源管理器中,雙擊media子文件夾。
注意.gif媒體文件表示您之前插入的圖像。
備注:
您 可能注意到圖像的文件名稱已經從Eagle1.gif更改為image1.gif了。更改的目的是為了解決隱私考慮,因為一個惡意用戶可以從文檔中的組件 名稱中獲得關於此組件的一些內容,例如一個圖像文件。例如,一個作者可能通過加密文檔中的文本部件來保護文檔內容。但是,如果兩個圖像 old_widget.gif and new_reenforced_widget.gif 被插入。即使文本被保護起來了,惡意用戶也能夠知道widget已經被更新了。使用像image1和image2這樣的通用圖像文件可以在Office Open XML格式文件中添加額外的保護。

20.

關閉SampleWordDocument.docx.zip ,不保存。

詳細的做法
http://www.cnblogs.com/end/archive/2008/08/06/1261755.html

2、如何使本地管理員帳戶臨時獲得SYSEM許可權

不用的吧?直接刪應該就可以

3、電腦藍屏,高手求救!

4、怎麼在ubuntu 12.04安裝32bit庫

這兩天在Ubuntu上安裝Oracle把人折騰毀了,即使照著網上的教程來,還是出了很多問題。好在最後終於搞定了。寫出來總結一下,免得以後忘了。
標題註明32位是因為網上教程幾乎全是以64位安裝為例的,32位系統下照著做是絕對會安裝失敗的。
出現的問題主要有兩方面,一個是安裝過程中出現的,另一個是安裝完成後出現的。
安裝過程(主要過程就直接copy別人的教程了)及問題:
1.將系統更新到最新:
sudo apt-get update
sudo apt-get dist-upgrade

2.如果使用的Ubuntu不是桌面版(如Ubuntu server),由於Oracle安裝需要用到圖形界面,所以需要安裝桌面程序:
sudo apt-get install gnome-core

相信很多都是使用的桌面版,那麼這個步驟就不需要了。
3. 安裝Oracle所需的依賴包:
sudo apt-get install automake
sudo apt-get install autotools-dev
sudo apt-get install binutils
sudo apt-get install bzip2
sudo apt-get install elfutils
sudo apt-get install expat
sudo apt-get install gawk
sudo apt-get install gcc
sudo apt-get install gcc-multilib
sudo apt-get install g++-multilib
sudo apt-get install ia32-libs
sudo apt-get install ksh
sudo apt-get install less
sudo apt-get install lesstif2
sudo apt-get install lesstif2-dev
sudo apt-get install lib32z1
sudo apt-get install lio1
sudo apt-get install lio-dev
sudo apt-get install libc6-dev
sudo apt-get install libc6-dev-i386
sudo apt-get install libc6-i386
sudo apt-get install libelf-dev
sudo apt-get install libltdl-dev
sudo apt-get install libmotif4
sudo apt-get install libodbcinstq4-1 libodbcinstq4-1:i386
sudo apt-get install libpth-dev
sudo apt-get install libpthread-stubs0
sudo apt-get install libpthread-stubs0-dev
sudo apt-get install libstdc++5
sudo apt-get install lsb-cxx
sudo apt-get install make
sudo apt-get install openssh-server
sudo apt-get install pdksh
sudo apt-get install rlwrap
sudo apt-get install rpm
sudo apt-get install sysstat
sudo apt-get install unixodbc
sudo apt-get install unixodbc-dev
sudo apt-get install unzip
sudo apt-get install x11-utils
sudo apt-get install zlibc
很多都是Ubuntu自帶的了,謹慎6起見都執行一遍吧。
4.創建用戶(此步可省略,直接使用當前的用戶即可,下面的安裝過程都是以不執行這一步為準的)
sudo groupadd oinstall
sudo groupadd dba
sudo useradd -g oinstall -G dba -d /opt/oracle -s /bin/bash oracle
sudo passwd oracle
5.檢查系統變數

/sbin/sysctl -a | grep sem
/sbin/sysctl -a | grep shm
/sbin/sysctl -a | grep file-max
/sbin/sysctl -a | grep aio-max
/sbin/sysctl -a | grep ip_local_port_range
/sbin/sysctl -a | grep rmem_default
/sbin/sysctl -a | grep rmem_max
/sbin/sysctl -a | grep wmem_default
/sbin/sysctl -a | grep wmem_max

然後根據上面命令中得到的參數值在/etc/sysctl.conf中增加對應數據,比如:
fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152kernel.shmmax = 536870912
kernel.shmmni = 4096kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048586
運行一下命令更新內核參數:
sysctl –p

6.添加對oracle用戶的內核限制在 /etc/security/limits.conf 文件中增加以下數據
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
oracle soft stack 10240
其中oracle是在第四步中創建的用戶,跳過第四步的話就寫當前用戶
7.查看/etc/pam.d/login,增加以下行(有了就不用增加了):
session required pam_limits.so
同樣檢查/etc/pam.d/su,沒有以下行就自己加上:
session required pam_limits.so

7.創建需要的文件夾(用於安裝oracle)並設置其所有權:
mkdir -p /opt/oracle
mkdir -p /opt/oraInventory

chown -R oracle:oinstall /opt/oracle
chown -R oracle:oinstall /opt/oraInventory

同樣,如果跳過了第四步,那就將所有權設置命令中的用戶oracle和組oinstall改為自己當前用戶和組(通常二者是一樣的),當然這時也可以不執行這兩個chown命令,本來目錄創建者就是所有者了。另外,需要root許可權執行這些命令(sudo,下同)
8.如果Ubuntu上沒安裝JRE的話,需要安裝JRE(我這里直接安裝了JDK,以JDK為例):
到Oracle官網下載JDK6(最新為7,考慮到兼容性問題,安裝6):
http://www.oracle.com/technetwork/java/javase/downloads/jdk6downloads-1902814.html
下載jdk-6u45-linux-i586.bin這個文件。放到主文件夾(home目錄)下,進入終端:
$sudo chmod 777 jdk-6u37-linux-x64.bin // 將文件賦予運行許可權
$sudo -s ./jdk-6u37-linux-x64.bin /usr/lib/jdk //將JDK安裝到/usr/lib/jdk 目錄下。

注意:最後安裝完成後可能安裝到了主文件夾下了,這是使用命令將其全部復制到/usr/lib/jdk目錄下即可。(如果沒有許可權,就使用sudo chmod 777獲取許可權再復制)
配置JDK的環境變數,使用編輯器打開主文件夾下的.bashrc配置文件(隱藏),向其中加入如下內容:
#JDK
JAVA_HOME=/usr/lib/jdk/jdk1.6.0_45
JRE_HOME=${JAVA_HOME}/jre
export ANDROID_JAVA_HOME=$JAVA_HOME
export CLASSPATH=.:${JAVA_HOME}/lib:$JRE_HOME/lib:$CLASSPATH
export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin
export JAVA_HOME;
export JRE_HOME;
export CLASSPATH;
HOME_BIN=~/bin/
export PATH=${PATH}:${JAVA_PATH}:${HOME_BIN};

注意核對一下目錄結構是不是正確的。
最後驗證JDK是否安裝正確:
java -version
出現了JDK版本信息就表示正確了。
9.為Oracle配置環境變數。同樣在主文件夾下的.bashrc配置文件中加入如下內容:
#Oracle
#這個寫剛剛創建的文件夾
export ORACLE_BASE=/opt/oracle
#這個後面可以隨便填寫
export ORACLE_HOME=$ORACLE_BASE/proct/11.2.0/dbhome_1
#資料庫的sid
export ORACLE_SID=orcl
export ORACLE_UNQNAME=orcl
#默認字元集
export NLS_LANG=.AL32UTF8
#環境變數
export PATH=${PATH}:${ORACLE_HOME}/bin/;

10.oracle本身並不支持ubuntu來安裝,所以要進行欺騙oracle的安裝程序(sudo執行):
ln -s /etc /etc/rc.d
ln -s /lib/i386-linux-gnu/libgcc_s.so.1 /lib/
ln -s /usr/bin/awk /bin/awk
ln -s /usr/bin/basename /bin/basename
ln -s /usr/bin/rpm /bin/rpm
ln -s /usr/lib/i386-linux-gnu/libpthread_nonshared.a /usr/lib/libpthread_nonshared.a

ln -s /usr/lib/i386-linux-gnu/libc_nonshared.a /usr/lib/libc_nonshared.a
ln -s /usr/lib/i386-linux-gnu/libstdc++.so.6 /lib/
ln -s /usr/lib/i386-linux-gnu/libstdc++.so.6 /usr/lib/

ln -s /usr/lib/i386-linux-gnu/libstdc++.so.5 /lib/
ln -s /usr/lib/i386-linux-gnu/libstdc++.so.5 /usr/lib/

echo 『Red Hat Linux release 5』 > /etc/redhat-release

注意:以上命令是對應於32位Ubuntu安裝32位Oracle的,如果是64位Ubuntu安裝64位Oracle,上面的i386-linux-gnu就都要改成x86_64-linux-gnu,目標目錄的lib也要改成lib64.(沒有lib64就新建一個)
因為Ubuntu將某些庫文件根據32位系統和64位系統分別存放了,但Oracle只認/usr/lib和/lib目錄,所以需要進行上面的軟鏈接。
11.下載Oracle安裝程序:
http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html

下載Linux x86的那兩個文件(64位系統就下Linux x86-64),解壓後得到database文件夾。
12.正式安裝Oracle,為database文件夾下的runInstaller文件賦予可執行許可權:
chmod 777 runInstaller
跳轉到database目錄,在終端下執行:
./runInstaller
此時可能會出現database目錄下部分文件的許可權不足,導致安裝程序無法啟動的問題,根據提示,對那些文件使用chmod 777進行授權就行了(貌似一共3個文件)。
啟動安裝圖形界面後,可能會發現文字亂碼,全是口口口:

這時可以關閉該界面,先在終端輸入:
export LANG=en_US
或者
export LANG=zh_CN.gbk
然後再執行:
./runInstaller

就可以在全英文界面下進行安裝了。
13.安裝前進行swap空間檢查時可能出現swap空間太小的問題,這一般是由於系統安裝時沒有創建swap分區,解決辦法是創建swap文件來開辟swap空間:
通過下面方法建立swap文件:
#dd if=/dev/zero of=/tmp/swapfree bs=32k count=65515 (count是分區數量,swap大小=bs*count,增加2G)
#mkswap /tmp/swapfree (格式化交換分區文件)
#swapon /tmp/swapfree (啟用交換分區文件)
#swapon –s (顯示swap狀態)
修改/etc/fstab,讓系統每次啟動都把/tmp/swapfree作為swap使用,增加下面一行:
/tmp/swapfree swap swap defaults 0 0

14.圖形安裝界面的第一步是填寫電子郵件,但是填完可能會出錯:Unexpected error occurred while validating inputs at state 'getOCMDetails'。這是由於缺少pdksh依賴包,簡單的解決辦法是不填寫郵件地址,不勾選下面的復選框,直接下一步,彈出提示後點『Yes』就能直接進入下一步了。完美的解決辦法可以到網上去看。

15.剩下的過程基本上很順利了,只需要設置一下密碼就行了,其他的設置都在啟動安裝程序前完成了,不要進行改動!
16.圖形界面下進行依賴檢查的時候會列出很多依賴檢查失敗了,無法進入下一步了,此時選中右上角的『忽略所有』就可以進入下一步了。
17.如果沒有嚴格按照前面的要求做,安裝過程中可能彈出錯誤,此時不要關閉界面,根據給出的日誌位置,在日誌中查看錯誤出現的原因,一般都是指定位置找不到相應的文件導致的,此時打開一個新的終端窗口,找到這些文件並將文件復制到對應的位置或者創建軟鏈接即可。(通常是/usr/lib目錄下找不到庫文件,這些庫文件都位於/usr/lib/i386-linux-gnu目錄下了)然後在圖形界面點擊「Retry『即可繼續安裝。
比如:「error in invoking target 'client_sharedlib' of makefile '/opt/oracle11g/server/rdbms/lib/ins_rdbms.mk''這個錯誤就是沒有執行:

ln -s /usr/lib/i386-linux-gnu/libpthread_nonshared.a /usr/lib/libpthread_nonshared.a

ln -s /usr/lib/i386-linux-gnu/libc_nonshared.a /usr/lib/libc_nonshared.a
這兩個命令導致的(針對32位安裝的情況)。
如果嚴格按照前面的要求做了,上面這種錯誤是不會出現的。另外,如果32位系統安裝64位Oracle或者64位系統安裝32位Oracle也是會彈出錯誤的,錯誤提示是這樣的:
Error in invoking target 'client_sharedlib' of makefile '/opt/app/oracle/proct/10.2.0/db_1/network/lib/ins_net_client.mk'

這種錯誤就只能重新下載正確的Oracle版本再進行安裝了。

5、我的電腦老是出現藍屏怎麼辦,

6、線程同步:何時互斥鎖不夠,還需要條件變數

信號量強調的是線程(或進程)間的同步:「信號量用在多線程多任務同步的,一個線程完成了某一個動作就通過信號量告訴別的線程,別的線程再進行某些動作(大家都 在sem_wait的時候,就阻塞在那裡)。當信號量為單值信號量是,也可以完成一個資源的互斥訪問。


有名信號量:可以用於不同進程間或多線程間的互斥與同步

創建打開有名信號量

sem_t *sem_open(const char *name, int oflag);

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);


成功返回信號量指針;失敗返回SEM_FAILED,設置errnoname是文件路徑名,但不能寫成/tmp/a.sem這樣的形式,因為在linux下,sem都是在/dev/shm目錄下,可寫成"/mysem"或"mysem",創建出來的文件都 是"/dev/shm/sem.mysem",mode設置為0666,value設置為信號量的初始值.所需信號燈等已存在條件下指定O_CREAT|O_EXCL卻是個錯誤。


關閉信號量,進程終止時,會自動調用它

int sem_close(sem_t *sem);

成功返回0;失敗返回-1,設置errno


刪除信號量,立即刪除信號量名字,當其他進程都關閉它時,銷毀它

int sem_unlink(const char *name);


等待信號量,測試信號量的值,如果其值小於或等於0,那麼就等待(阻塞);一旦其值變為大於0就將它減1,並返回

int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);


成功返回0;失敗返回-1,設置errno


當信號量的值為0時,sem_trywait立即返回,設置errno為EAGAIN。如果被某個信號中斷,sem_wait會過早地返回,設置errno為EINTR


發出信號量,給它的值加1,然後喚醒正在等待該信號量的進程或線程

int sem_post(sem_t *sem);


成功返回0;失敗返回-1,不會改變它的值,設置errno,該函數是非同步信號安全的,可以在信號處理程序里調用它無名信號量,用於進程體內各線程間的互斥和同步,使用如下API(無名信號量,基於內存的信號量)


(1)、sem_init


功能:用於創建一個信號量,並初始化信號量的值。


頭文件:


函數原型: int sem_init (sem_t* sem, int pshared, unsigned int value);


函數傳入值: sem:信號量。pshared:決定信號量能否在幾個進程間共享。由於目前LINUX還沒有實現進程間共享信息量,所以這個值只能取0。


(2)其他函數。

int sem_wait (sem_t* sem);

int sem_trywait (sem_t* sem);

int sem_post (sem_t* sem);

int sem_getvalue (sem_t* sem);

int sem_destroy (sem_t* sem);


功能:sem_wait和sem_trywait相當於P操作,它們都能將信號量的值減一,兩者的區別在於若信號量的值小於零時,sem_wait將會阻塞進程,而sem_trywait則會立即返回。sem_post相當於V操作,它將信號量的值加一,同時發出喚醒的信號給等待的進程(或線程)。


sem_getvalue 得到信號量的值。


sem_destroy 摧毀信號量。


如果某個基於內存的信號燈是在不同進程間同步的,該信號燈必須存放在共享內存區中,這要只要該共享內存區存在,該信號燈就存在。


互斥鎖(又名互斥量)強調的是資源的訪問互斥:互斥鎖是用在多線程多任務互斥的,一個線程佔用了某一個資源,那麼別的線程就無法訪問,直到這個線程unlock,其他的線程才開始可以利用這個資源。比如對全局變數的訪問,有時要加鎖,操作完了,在解鎖。有的時候鎖和信號量會同時使用的」


也就是說,信號量不一定是鎖定某一個資源,而是流程上的概念,比如:有A,B兩個線程,B線程要等A線程完成某一任務以後再進行自己下面的步驟,這個任務並不一定是鎖定某一資源,還可以是進行一些計算或者數據處理之類。而線程互斥量則是「鎖住某一資源」的概念,在鎖定期間內,其他線程無法對被保護的數據進行操作。在有些情況下兩者可以互換。


在linux下, 線程的互斥量數據類型是pthread_mutex_t. 在使用前, 要對它進行初始化:


對於靜態分配的互斥量, 可以把它設置為PTHREAD_MUTEX_INITIALIZER, 或者調用pthread_mutex_init.


對於動態分配的互斥量, 在申請內存(malloc)之後, 通過pthread_mutex_init進行初始化, 並且在釋放內存(free)前需要調用pthread_mutex_destroy.

原型:

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr);

int pthread_mutex_destroy(pthread_mutex_t *mutex);


頭文件:


返回值: 成功則返回0, 出錯則返回錯誤編號.


說明: 如果使用默認的屬性初始化互斥量, 只需把attr設為NULL. 其他值在以後講解.


首先說一下加鎖函數:


頭文件:

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);


返回值: 成功則返回0, 出錯則返回錯誤編號.


說 明: 具體說一下trylock函數, 這個函數是非阻塞調用模式, 也就是說, 如果互斥量沒被鎖住, trylock函數將把互斥量加鎖, 並獲得對共享資源的訪問許可權; 如果互斥量 被鎖住了, trylock函數將不會阻塞等待而直接返回EBUSY, 表示共享資源處於忙狀態.


再說一下解所函數:


頭文件:

原型: int pthread_mutex_unlock(pthread_mutex_t *mutex);


返回值: 成功則返回0, 出錯則返回錯誤編號.


條件變數常與互斥鎖同時使用,達到線程同步的目的:條件變數通過允許線程阻塞和等待另一個線程發送信號的方法彌補了互斥鎖的不足。在發 送信號時,如果沒有線程 等待在該條件變數上,那麼信號將丟失;而信號量有計數值,每次信號量post操作都會被記錄


互斥鎖必須是誰上鎖就由誰來解鎖,而信號量的wait和post操作不必由同一個線程執行。

2. 互斥鎖要麼被鎖住,要麼被解開,和二值信號量類似


3. sem_post是各種同步技巧中,唯一一個能在信號處理程序中安全調用的函數


4. 互斥鎖是為上鎖而優化的;條件變數是為等待而優化的; 信號量既可用於上鎖,也可用於等待,因此會有更多的開銷和更高的復雜性


5. 互斥鎖,條件變數都只用於同一個進程的各線程間,而信號量(有名信號量)可用於不同進程間的同步。當信號量用於進程間同步時,要求信號量建立在共享內存區。


6. 信號量有計數值,每次信號量post操作都會被記錄,而條件變數在發送信號時,如果沒有線程在等待該條件變數,那麼信號將丟失。


讀寫鎖


讀寫鎖與互斥量類似,不過讀寫鎖允許更高的並行性。互斥量要麼是鎖住狀態要麼是不加鎖狀態,而且一次只有一個線程可以對其加鎖。


讀寫鎖可以由三種狀態:讀模式下加鎖狀態、寫模式下加鎖狀態、不加鎖狀態。一次只有一個線程可以佔有寫模式的讀寫鎖,但是多個線程可以同時佔有讀模式的讀寫

鎖。


在讀寫鎖是寫加鎖狀態時,在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的線程都會被阻塞。當讀寫鎖在讀加鎖狀態時,所有試圖以讀模式對它進行加鎖的線程都可以得到訪問權,但是如果線程希望以寫模式對此鎖進行加鎖,它必須阻塞直到所有的線程釋放讀鎖。雖然讀寫鎖的實現各不相同,但當讀寫鎖處於讀模式鎖住狀態時,如果有另外的線程試圖以寫模式加鎖,讀寫鎖通常會阻塞隨後的讀模式鎖請求。這樣可以避免讀模式鎖長期佔用,而等待的寫模式鎖請求一直得不到滿足。


讀寫鎖非常適合於對數據結構讀的次數遠大於寫的情況。當讀寫鎖在寫模式下時,它所保護的數據結構就可以被安全地修改,因為當前只有一個線程可以在寫模式下擁 有這個鎖。當讀寫鎖在讀狀態下時,只要線程獲取了讀模式下的讀寫鎖,該鎖所保護的數據結構可以被多個獲得讀模式鎖的線程讀取。


讀寫鎖也叫做共享-獨占鎖,當讀寫鎖以讀模式鎖住時,它是以共享模式鎖住的;當他以寫模式鎖住時,它是以獨占模式鎖住的。

初始化和銷毀:

#include

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);


成功則返回0, 出錯則返回錯誤編號.


同互斥量以上, 在釋放讀寫鎖佔用的內存之前, 需要先通過thread_rwlock_destroy對讀寫鎖進行清理工作, 釋放由init分配的資源.


讀和寫:

#include

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);


成功則返回0, 出錯則返回錯誤編號.


這3個函數分別實現獲取讀鎖, 獲取寫鎖和釋放鎖的操作. 獲取鎖的兩個函數是阻塞操作, 同樣, 非阻塞的函數為:

#include

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);


成功則返回0, 出錯則返回錯誤編號.


非阻塞的獲取鎖操作, 如果可以獲取則返回0, 否則返回錯誤的EBUSY.


雖然讀寫鎖提高了並行性,但是就速度而言並不比互斥量快.


可能這也是即使有讀寫鎖存在還會使用互斥量的原因,因為他在速度方面略勝一籌。這就需要我們在寫程序的時候綜合考慮速度和並行性並找到一個折中。


比如: 假設使用互斥量需要0.5秒,使用讀寫鎖需要0.8秒。在類似學生管理系統這類軟體中,可能百分之九十的時間都是查詢操作,那麼假如現在突然來個個20個請求,如果使用的是互斥量,那麼最後的那個查詢請求被滿足需要10後。這樣,估計沒人能受得了。而使用讀寫鎖,應為 讀鎖能夠多次獲得。所以所有的20個請求,每個請求都能在1秒左右得到滿足。


也就是說,在一些寫操作比較多或是本身需要同步的地方並不多的程序中我們應該使用互斥量,而在讀操作遠大於寫操作的一些程序中我們應該使用讀寫鎖來進行同步


條件變數(condition)


條件變數與互斥量一起使用時,允許線程以無競爭的方式等待特定的條件發生。


條件本身是由互斥量保護的。線程在改變條件狀態前必須首先鎖住互斥量,其它線程在獲得互斥量之前不會察覺到這種改變,因此必須鎖定互斥量以後才能計算條件。


條件的檢測是在互斥鎖的保護下進行的。如果一個條件為假,一個線程自動阻塞,並釋放等待狀態改變的互斥鎖。如果另一個線程改變了條件,它發信號給關聯的條件


變數,喚醒一個或多個等待它的線程,重新獲得互斥鎖,重新評價條件。如果兩進程共享可讀寫的內存,條件變數可以被用來實現這兩進程間的線程同步。


初始化:

條件變數採用的數據類型是pthread_cond_t, 在使用之前必須要進行初始化, 這包括兩種方式:


靜態: 可以把常量PTHREAD_COND_INITIALIZER給靜態分配的條件變數.

動態: pthread_cond_init函數, 是釋放動態條件變數的內存空間之前, 要用pthread_cond_destroy對其進行清理.

#include

int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);

int pthread_cond_destroy(pthread_cond_t *cond);


成功則返回0, 出錯則返回錯誤編號.


注意:條件變數佔用的空間並未被釋放。


當pthread_cond_init的attr參數為NULL時, 會創建一個默認屬性的條件變數; 非默認情況以後討論.


2. 等待條件:

#include

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);

int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);


成功則返回0, 出錯則返回錯誤編號.


這兩個函數分別是阻塞等待和超時等待.


等待條件函數等待條件變為真, 傳遞給pthread_cond_wait的互斥量對條件進行保護, 調用者把鎖住的互斥量傳遞給函數. 函數把調用線程放到等待條件的線程列表上, 然後對互斥量解鎖, 這兩個操作是原子的. 這樣 便關閉了條件檢查和線程進入休眠狀態等待條件改變這兩個操作之間的時間通道, 這樣線程就不會錯過條件的任何變化.


當pthread_cond_wait返回時, 互斥量再次被鎖住.


pthread_cond_wait函數的返回並不意味著條件的值一定發生了變化,必須重新檢查條件的值。


pthread_cond_wait函數返回時,相應的互斥鎖將被當前線程鎖定,即使是函數出錯返回。


阻塞在條件變數上的線程被喚醒以後,直到pthread_cond_wait()函數返回之前條件的值都有可能發生變化。所以函數返回以後,在鎖定相應的互斥鎖之前,必須重新測試條 件值。最好的測試方法是循環調用pthread_cond_wait函數,並把滿足條件的表達式置為循環的終止條件。如:


pthread_mutex_lock();


while (condition_is_false)


pthread_cond_wait();


pthread_mutex_unlock();


阻塞在同一個條件變數上的不同線程被釋放的次序是不一定的。


注意:pthread_cond_wait()函數是退出點,如果在調用這個函數時,已有一個掛起的退出請求,且線程允許退出,這個線程將被終止並開始執行善後處理函數,而這時和條 件變數相關的互斥鎖仍將處在鎖定狀態。


pthread_cond_timedwait函數到了一定的時間,即使條件未發生也會解除阻塞。這個時間由參數abstime指定。函數返回時,相應的互斥鎖往往是鎖定的,即使是函數出錯返回。


注意:pthread_cond_timedwait函數也是退出點。


超時時間參數是指一天中的某個時刻。使用舉例:


pthread_timestruc_t to;


to.tv_sec = time(NULL) + TIMEOUT;


to.tv_nsec = 0;


超時返回的錯誤碼是ETIMEDOUT。


3. 通知條件:

#include

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);


成功則返回0, 出錯則返回錯誤編號.


這兩個函數用於通知線程條件已經滿足. 調用這兩個函數, 也稱向線程或條件發送信號. 必須注意, 一定要在改變條件狀態以後再給線程發送信號.

7、linux信號燈使用sem_open的錯誤 sem_open_test.c:(.text+0x4c):對『sem_open』未定義的引用

g

8、linux task_struct的結構注釋

1. 調度數據成員
(1) volatile long states;
表示進程的當前狀態:
? TASK_RUNNING:正在運行或在就緒隊列run-queue中准備運行的進程,實際參與進程調度。
? TASK_INTERRUPTIBLE:處於等待隊列中的進程,待資源有效時喚醒,也可由其它進程通過信號(signal)或定時中斷喚醒後進入就緒隊列run-queue。
? TASK_UNINTERRUPTIBLE:處於等待隊列中的進程,待資源有效時喚醒,不可由其它進程通過信號(signal)或定時中斷喚醒。
? TASK_ZOMBIE:表示進程結束但尚未消亡的一種狀態(僵死狀態)。此時,進程已經結束運行且釋放大部分資源,但尚未釋放進程式控制制塊。
?TASK_STOPPED:進程被暫停,通過其它進程的信號才能喚醒。導致這種狀態的原因有二,或者是對收到SIGSTOP、SIGSTP、SIGTTIN或SIGTTOU信號的反應,或者是受其它進程的ptrace系統調用的控制而暫時將CPU交給控制進程。
? TASK_SWAPPING: 進程頁面被交換出內存的進程。
(2) unsigned long flags;
進程標志:
?PF_ALIGNWARN 列印「對齊」警告信息。
?PF_PTRACED 被ptrace系統調用監控。
?PF_TRACESYS 正在跟蹤。
?PF_FORKNOEXEC 進程剛創建,但還沒執行。
?PF_SUPERPRIV 超級用戶特權。
?PF_DUMPCORE mped core。
?PF_SIGNALED 進程被信號(signal)殺出。
?PF_STARTING 進程正被創建。
?PF_EXITING 進程開始關閉。
?PF_USEDFPU 該進程使用FPU(SMP only)。
?PF_DTRACE delayed trace (used on m68k)。
(3) long priority;
進程優先順序。 Priority的值給出進程每次獲取CPU後可使用的時間(按jiffies計)。優先順序可通過系統調用sys_setpriorty改變(在kernel/sys.c中)。
(4) unsigned long rt_priority;
rt_priority 給出實時進程的優先順序,rt_priority+1000給出進程每次獲取CPU後可使用的時間(同樣按jiffies計)。實時進程的優先順序可通過系統 調用sys_sched_setscheler()改變(見kernel/sched.c)。
(5) long counter;
在 輪轉法調度時表示進程當前還可運行多久。在進程開始運行是被賦為priority的值,以後每隔一個tick(時鍾中斷)遞減1,減到0時引起新一輪調 度。重新調度將從run_queue隊列選出counter值最大的就緒進程並給予CPU使用權,因此counter起到了進程的動態優先順序的作用 (priority則是靜態優先順序)。
(6) unsigned long policy;
該進程的進程調度策略,可以通過系統調用sys_sched_setscheler()更改(見kernel/sched.c)。調度策略有:
?SCHED_OTHER 0 非實時進程,基於優先權的輪轉法(round robin)。
?SCHED_FIFO 1 實時進程,用先進先出演算法。
?SCHED_RR 2 實時進程,用基於優先權的輪轉法。
2. 信號處理
(1) unsigned long signal;
進程接收到的信號。每位表示一種信號,共32種。置位有效。
(2) unsigned long blocked;
進程所能接受信號的位掩碼。置位表示屏蔽,復位表示不屏蔽。
(3) struct signal_struct *sig;
因 為signal和blocked都是32位的變數,Linux最多隻能接受32種信號。對每種信號,各進程可以由PCB的sig屬性選擇使用自定義的處理 函數,或是系統的預設處理函數。指派各種信息處理函數的結構定義在include/linux/sched.h中。對信號的檢查安排在系統調用結束後,以 及「慢速型」中斷服務程序結束後(IRQ#_interrupt(),參見9。5節「啟動內核」)。
3. 進程隊列指針
(1) struct task_struct *next_task,*prev_task;
所有進程(以PCB的形式)組成一個雙向鏈表。next_task和就是鏈表的前後指針。鏈表的頭和尾都是init_task(即0號進程)。
(2) struct task_struct *next_run,*prev_run;
由正在運行或是可以運行的,其進程狀態均為TASK_RUNNING的進程所組成的一個雙向循環鏈表,即run_queue就緒隊列。該鏈表的前後向指針用next_run和prev_run,鏈表的頭和尾都是init_task(即0號進程)。
(3) struct task_struct *p_opptr,*p_pptr;和struct task_struct *p_cptr,*p_ysptr,*p_osptr;
以上分別是指向原始父進程(original parent)、父進程(parent)、子進程(youngest child)及新老兄弟進程(younger sibling,older sibling)的指針。

4. 進程標識
(1) unsigned short uid,gid;
uid和gid是運行進程的用戶標識和用戶組標識。
(2) int groups[NGROUPS];
與多數現代UNIX操作系統一樣,Linux允許進程同時擁有一組用戶組號。在進程訪問文件時,這些組號可用於合法性檢查。
(3) unsigned short euid,egid;
euid 和egid又稱為有效的uid和gid。出於系統安全的許可權的考慮,運行程序時要檢查euid和egid的合法性。通常,uid等於euid,gid等於 egid。有時候,系統會賦予一般用戶暫時擁有root的uid和gid(作為用戶進程的euid和egid),以便於進行運作。
(4) unsigned short fsuid,fsgid;
fsuid 和fsgid稱為文件系統的uid和gid,用於文件系統操作時的合法性檢查,是Linux獨特的標識類型。它們一般分別和euid和egid一致,但在 NFS文件系統中NFS伺服器需要作為一個特殊的進程訪問文件,這時只修改客戶進程的fsuid和fsgid。
(5) unsigned short suid,sgid;
suid和sgid是根據POSIX標准引入的,在系統調用改變uid和gid時,用於保留真正的uid和gid。
(6) int pid,pgrp,session;
進程標識號、進程的組織號及session標識號,相關系統調用(見程序kernel/sys.c)有sys_setpgid、sys_getpgid、sys_setpgrp、sys_getpgrp、sys_getsid及sys_setsid幾種。
(7) int leader;
是否是session的主管,布爾量。
5. 時間數據成員
(1) unsigned long timeout;
用於軟體定時,指出進程間隔多久被重新喚醒。採用tick為單位。
(2) unsigned long it_real_value,it_real_iner;
用 於itimer(interval timer)軟體定時。採用jiffies為單位,每個tick使it_real_value減到0時向進程發信號SIGALRM,並重新置初值。初值由 it_real_incr保存。具體代碼見kernel/itimer.c中的函數it_real_fn()。
(3) struct timer_list real_timer;
一種定時器結構(Linux共有兩種定時器結構,另一種稱作old_timer)。數據結構的定義在include/linux/timer.h中,相關操作函數見kernel/sched.c中add_timer()和del_timer()等。
(4) unsigned long it_virt_value,it_virt_incr;
關 於進程用戶態執行時間的itimer軟體定時。採用jiffies為單位。進程在用戶態運行時,每個tick使it_virt_value減1,減到0時 向進程發信號SIGVTALRM,並重新置初值。初值由it_virt_incr保存。具體代碼見kernel/sched.c中的函數 do_it_virt()。
(5) unsigned long it_prof_value,it_prof_incr;
同樣是 itimer軟體定時。採用jiffies為單位。不管進程在用戶態或內核態運行,每個tick使it_prof_value減1,減到0時向進程發信號 SIGPROF,並重新置初值。初值由it_prof_incr保存。 具體代碼見kernel/sched.c中的函數do_it_prof。
(6) long utime,stime,cutime,cstime,start_time;
以上分別為進程在用戶態的運行時間、進程在內核態的運行時間、所有層次子進程在用戶態的運行時間總和、所有層次子進程在核心態的運行時間總和,以及創建該進程的時間。
6. 信號量數據成員
(1) struct sem_undo *semundo;
進 程每操作一次信號量,都生成一個對此次操作的undo操作,它由sem_undo結構描述。這些屬於同一進程的undo操作組成的鏈表就由semundo 屬性指示。當進程異常終止時,系統會調用undo操作。sem_undo的成員semadj指向一個數據數組,表示各次undo的量。結構定義在 include/linux/sem.h。
(2) struct sem_queue *semsleeping;
每一信號量集合對應一 個sem_queue等待隊列(見include/linux/sem.h)。進程因操作該信號量集合而阻塞時,它被掛到semsleeping指示的關 於該信號量集合的sem_queue隊列。反過來,semsleeping。sleeper指向該進程的PCB。
7. 進程上下文環境
(1) struct desc_struct *ldt;
進程關於CPU段式存儲管理的局部描述符表的指針,用於模擬WINE Windows的程序。其他情況下取值NULL,進程的ldt就是arch/i386/traps.c定義的default_ldt。
(2) struct thread_struct tss;
任務狀態段,其內容與INTEL CPU的TSS對應,如各種通用寄存器.CPU調度時,當前運行進程的TSS保存到PCB的tss,新選中進程的tss內容復制到CPU的TSS。結構定義在include/linux/tasks.h中。
(3) unsigned long saved_kernel_stack;
為MS-DOS的模擬程序(或叫系統調用vm86)保存的堆棧指針。
(4) unsigned long kernel_stack_page;
在內核態運行時,每個進程都有一個內核堆棧,其基地址就保存在kernel_stack_page中。
8. 文件系統數據成員
(1) struct fs_struct *fs;
fs 保存了進程本身與VFS的關系消息,其中root指向根目錄結點,pwd指向當前目錄結點,umask給出新建文件的訪問模式(可由系統調用umask更 改),count是Linux保留的屬性,如下頁圖所示。結構定義在include/linux/sched.h中。
(2) struct files_struct *files;
files包含了進程當前所打開的文件(struct file *fd[NR_OPEN])。在Linux中,一個進程最多隻能同時打開NR_OPEN個文件。而且,前三項分別預先設置為標准輸入、標准輸出和出錯消息輸出文件。
(3) int link_count;
文件鏈(link)的數目。
9. 內存數據成員
(1) struct mm_struct *mm;
在linux 中,採用按需分頁的策略解決進程的內存需求。task_struct的數據成員mm指向關於存儲管理的mm_struct結構。其中包含了一個虛存隊列 mmap,指向由若干vm_area_struct描述的虛存塊。同時,為了加快訪問速度,mm中的mmap_avl維護了一個AVL樹。在樹中,所有的 vm_area_struct虛存塊均由左指針指向相鄰的低虛存塊,右指針指向相鄰的高虛存塊。 結構定義在include/linux/sched.h中。
10. 頁面管理
(1) int swappable:1;
進程佔用的內存頁面是否可換出。swappable為1表示可換出。對該標志的復位和置位均在do_fork()函數中執行(見kerenl/fork.c)。
(2) unsigned long swap_address;
虛存地址比swap_address低的進程頁面,以前已經換出或已換出過,進程下一次可換出的頁面自swap_address開始。參見swap_out_process()和swap_out_pmd()(見mm/vmscan.c)。
(3) unsigned long min_flt,maj_flt;
該 進程累計的minor缺頁次數和major缺頁次數。maj_flt基本與min_flt相同,但計數的范圍比後者廣(參見fs/buffer.c和 mm/page_alloc.c)。min_flt只在do_no_page()、do_wp_page()里(見mm/memory.c)計數新增的可 以寫操作的頁面。
(4) unsigned long nswap;
該進程累計換出的頁面數。
(5) unsigned long cmin_flt,cmaj_flt,cnswap;
以本進程作為祖先的所有層次子進程的累計換入頁面、換出頁面計數。
(6) unsigned long old_maj_flt,dec_flt;
(7) unsigned long swap_cnt;
下一次信號最多可換出的頁數。
11. 支持對稱多處理器方式(SMP)時的數據成員
(1) int processor;
進程正在使用的CPU。
(2) int last_processor;
進程最後一次使用的CPU。
(3) int lock_depth;
上下文切換時系統內核鎖的深度。
12. 其它數據成員
(1) unsigned short used_math;
是否使用FPU。
(2) char comm[16];
進程正在運行的可執行文件的文件名。
(3) struct rlimit rlim[RLIM_NLIMITS];
結 構rlimit用於資源管理,定義在linux/include/linux/resource.h中,成員共有兩項:rlim_cur是資源的當前最大 數目;rlim_max是資源可有的最大數目。在i386環境中,受控資源共有RLIM_NLIMITS項,即10項,定義在 linux/include/asm/resource.h中,見下表:
(4) int errno;
最後一次出錯的系統調用的錯誤號,0表示無錯誤。系統調用返回時,全程量也擁有該錯誤號。
(5) long debugreg[8];
保存INTEL CPU調試寄存器的值,在ptrace系統調用中使用。
(6) struct exec_domain *exec_domain;
Linux可以運行由80386平台其它UNIX操作系統生成的符合iBCS2標準的程序。關於此類程序與Linux程序差異的消息就由exec_domain結構保存。
(7) unsigned long personality;
Linux 可以運行由80386平台其它UNIX操作系統生成的符合iBCS2標準的程序。 Personality進一步描述進程執行的程序屬於何種UNIX平台的「個性」信息。通常有PER_Linux、PER_Linux_32BIT、 PER_Linux_EM86、PER_SVR3、PER_SCOSVR3、PER_WYSEV386、PER_ISCR4、PER_BSD、 PER_XENIX和PER_MASK等,參見include/linux/personality.h。
(8) struct linux_binfmt *binfmt;
指向進程所屬的全局執行文件格式結構,共有a。out、script、elf和java等四種。結構定義在include/linux/binfmts.h中(core_mp、load_shlib(fd)、load_binary、use_count)。
(9) int exit_code,exit_signal;
引起進程退出的返回代碼exit_code,引起錯誤的信號名exit_signal。
(10) int mpable:1;
布爾量,表示出錯時是否可以進行memory mp。
(11) int did_exec:1;
按POSIX要求設計的布爾量,區分進程是正在執行老程序代碼,還是在執行execve裝入的新代碼。
(12) int tty_old_pgrp;
進程顯示終端所在的組標識。
(13) struct tty_struct *tty;
指向進程所在的顯示終端的信息。如果進程不需要顯示終端,如0號進程,則該指針為空。結構定義在include/linux/tty.h中。
(14) struct wait_queue *wait_chldexit;
在進程結束時,或發出系統調用wait4後,為了等待子進程的結束,而將自己(父進程)睡眠在該隊列上。結構定義在include/linux/wait.h中。
13. 進程隊列的全局變數
(1) current;
當前正在運行的進程的指針,在SMP中則指向CPU組中正被調度的CPU的當前進程:
#define current(0+current_set[smp_processor_id()])/*sched.h*/
struct task_struct *current_set[NR_CPUS];
(2) struct task_struct init_task;
即0號進程的PCB,是進程的「根」,始終保持初值INIT_TASK。
(3) struct task_struct *task[NR_TASKS];
進 程隊列數組,規定系統可同時運行的最大進程數(見kernel/sched.c)。NR_TASKS定義在include/linux/tasks.h 中,值為512。每個進程佔一個數組元素(元素的下標不一定就是進程的pid),task[0]必須指向init_task(0號進程)。可以通過 task[]數組遍歷所有進程的PCB。但Linux也提供一個宏定義for_each_task()(見 include/linux/sched.h),它通過next_task遍歷所有進程的PCB:
#define for_each_task(p) \
for(p=&init_task;(p=p->next_task)!=&init_task;)
(4) unsigned long volatile jiffies;
Linux的基準時間(見kernal/sched.c)。系統初始化時清0,以後每隔10ms由時鍾中斷服務程序do_timer()增1。
(5) int need_resched;
重新調度標志位(見kernal/sched.c)。當需要Linux調度時置位。在系統調用返回前(或者其它情形下),判斷該標志是否置位。置位的話,馬上調用schele進行CPU調度。
(6) unsigned long intr_count;
記 錄中斷服務程序的嵌套層數(見kernal/softirq.c)。正常運行時,intr_count為0。當處理硬體中斷、執行任務隊列中的任務或者執 行bottom half隊列中的任務時,intr_count非0。這時,內核禁止某些操作,例如不允許重新調度。

與semopen許可權位相關的知識