Linux進程、線程、內核操作函數

進程

1.        替換進程鏡像

#include <unistd.h>

       extern char **environ;

       int execl(const char *path, const char*arg, ..., (char*)0);

       int execlp(const char *file, const char*arg, ..., (char*)0);

       int execle(const char *path, const char*arg, ..., char * const envp[]);

       int execv(const char *path, char *constargv[]);

       int execvp(const char *file, char *constargv[]);

           int execve(const char *file, char *const argv[], char *const envp[]);

1)        execl、execlp、execle參數可變,以空指針結束;execv、execvp第二個參數爲一字符串數組。

2)        函數會把argv參數傳遞給main函數。

3)        以p結尾的函數會搜索PATH環境變量來查找新程序,不存在則使用絕對路徑來傳遞給函數。

4)        exec函數不會返回調用它的函數。

2.        複製進程對象

#include <unistd.h>

#include<sys/types.h>

pid_t fork(void);

新進程與原進程一模一樣,執行代碼完全一樣,只是有自己的數據空間、環境以及文件描述符。

返回值:

-1:創建失敗;

0:當前進程爲子進程;

非零:當前進程爲父進程。

3.        進程等待

#include<sys/types.h>

#include<sys/wait.h>

pid_t wait(int*stat_loc);

pid_t waitpid(pid_t pid, int* stat_loc, int options);

int waitid(idtype_tidtype, id_t id, siginfo_t *infop, int options);

暫停父進程知道子進程結束爲止。

stat_loc:

WIFEXITED

子進程正常結束,WIFEXITD(stat_loc)取非零值

WEXITSTATUS

WEXITSTATUS(stat_loc)非零時,爲進程退出碼

WIFSIGNALED

如果子進程因一個爲捕獲的信號終止,WIFSIGNALED(stat_loc)非零

WTERMSIG

WTERMSIG(stat_loc)非零,則爲信號代碼

WCOREDUMP

子進程意外終止,WCOREDUMP(stat_loc)取非零

WIFSTOPPED

WIFSTOPPED(stat_loc)非零,則爲一個信號代碼

 

4.        exit

退出進程。

進程通訊、信號

Linux 提供的大多數信號類型是供內核使用的,只有少數的幾種信號可以用作在進程之間傳送。下面給出常用的信號和它們的意義:

SIGHUP

當終止一個終端時,內核就把這一種信號發送給該終端所控制的所有進程。通常情況

下,一個進程組的控制終端是該用戶擁有的終端,但不完全是如此。當進程組的首進程結

束時,就會向該進程組的所有進程發送這種信號。這就可以保證當一個用戶退出使用時,

其後臺進程被終止,除非有其它方面的安排。

SIGINT

當一個用戶按了中斷鍵(一般爲Ctrl+C)後,內核就向與該終端有關聯的所有進程發

送這種信號。它提供了中止運行程序的簡便方法。

SIGQUIT

這種信號與SIGINT 非常相似,當用戶按了退出鍵時(爲ASCII 碼FS,通常爲Ctrl+\),

內核就發送出這種信號。SIGQUIT 將形成POSIX 標準所描述的非正常終止。我們稱這種

UNIX 實現的實際操作爲核心轉貯(core dump),並用信息“Quit (coredump)”指出這一操

作的發生。這時,該進程的映象被轉貯到一個磁盤文件中,供調試之用。

SIGILL

當一個進程企圖執行一條非法指令時,內核就發出這種信號。例如,在沒有相應硬件

支撐的條件下,企圖執行一條浮點指令時,則會引起這種信號的發生。SIGILL 和SIGQUIT

一樣,也形成非正常終止。

SIGTRAP

這是一種由調試程序使用的專用信號。由於他的專用行和特殊性,我們不再對它作進一步的討論。SIGTRAP 也形成非正常終止。

SIGFPE

當產生浮點錯誤時(比如溢出),內核就發出這種信號,它導致非正常終止。

SIGKILL

這是一個相當特殊的信號,它從一個進程發送到另一個進程,使接收到該信號的進程

終止。內核偶爾也會發出這種信號。SIGKILL 的特點是,它不能被忽略和捕捉,只能通過

用戶定義的相應中斷處理程序而處理該信號。因爲其它的所有信號都能被忽略和捕捉,所

以只有這種信號能絕對保證終止一個進程。

SIGALRM

當一個定時器到時的時候,內核就向進程發送這個信號。定時器是由改進程自己用系

統調用alarm()設定的。

SIGTERM

這種信號是由系統提供給普通程序使用的,按照規定,它被用來終止一個進程。

SIGSTOP

這個信號使進程暫時中止運行,系統將控制權轉回正在等待運行的下一個進程。

SIGUSR1 和SIGUSR2

和SIGTERM 一樣,這兩種信號不是內核發送的,可以用於用戶所希望的任何目的。

SIGCHLD

子進程結束信號。UNIX 中用它來實現系統調用exit()和wait()。執行exit()時,就向子進程的父進程發送SIGCHLD 信號,如果這時父進程政在執行wait(),則它被喚醒;如果這時候父進程不是執行wait(),則此父進程不會捕捉SIGCHLD 信號,因此該信號不起作用,子進程進入過渡狀態(如果父進程忽略SIGCHLD,子進程就結束而不會進入過渡狀態)。這個機制對大多數UNIX 程序員來說是相當重要的。

信號與處理

1.        發送信號

#include <unistd.h>

unsigned  int alarm(unisigned int seconds);在seconds後發送一個SIGALRM信號

intkill(pid_t pid, int sig);發送信號到指定進程

2.        信號處理

int signal(int sig, __sighandler_t handler);

sig: 指明瞭所要處理的信號類型,它可以取除了SIGKILL 和SIGSTOP 外的任何一種信號。

handler:可以取以下三種值:

1)       一個返回值爲整數的函數地址。

此函數必須在signal()被調用前聲明,handler 中爲這個函數的名字。當接收到一個類型爲sig 的信號時,就執行handler 所指定的函數。這個函數應有如下形式的定義:

int func(int sig);

sig 是傳遞給它的唯一參數。執行了signal()調用後,進程只要接收到類型爲sig 的信號,

不管其正在執行程序的哪一部分,就立即執行func()函數。當func()函數執行結束後,控制

權返回進程被中斷的那一點繼續執行。

2)        SIG_IGN

這個符號表示忽略信號。執行了相應的signal()調用好,進程會忽略類型爲sig 的信號。

3)       SIG_DFL

這個符號表示恢復系統對信號的默認處理。

進程間通信(管道)

1.       #include <unistd.h>

Int pipe(intfd[2]);

功能:獲取兩個管道描述符;

返回值:-1表示失敗,0表示成功。

2.       標準I/O函數中的管道

#include<stdio.h>

FILE *popen(constchar *cmdstring, const char *type);

int pclose(FILE*pf);

popen的功能:創建一個管道,然後調用fork產生一個子進程,調用exec執行cmdstring命令,關閉管道不使用短,執行shell以運行命令,然後等待命令終止。

參數:

cmdstring :需要執行的shell命令。

type:若爲”r”,命令連接至標準輸出;若爲”w”,命令連接至標準輸入。

3.        

多線程

1.        創建一個線程的函數:

         #include<pthread.h>

         intpthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void),void *restrict arg);

 

         返回值:若是成功建立線程返回0,否則返回錯誤的編號

         參數:

                   pthread_t*restrict tidp 要創建的線程的線程id指針

                   constpthread_attr_t *restrict attr 創建線程時的線程屬性

                   void* (start_rtn)(void)返回值是void類型的指針函數

                   void *restrictarg start_rtn的形參

 

                   一般可以這樣用:

                   pthread_create(&id2,NULL, (void*)myThread1, NULL);

2.        等待一個線程的結束:pthread_join()函數,以阻塞的方式等待thread指定的線程結束

                   #include<pthread.h>

                    int pthread_join(pthread_t thread, void**retval);

                   返回值:

                            0代表成功。 失敗,返回的則是錯誤號

                   參數:

                            thread:線程標識符,即線程ID,標識唯一線程。

                         retval:用戶定義的指針,用來存儲被等待線程的返回值。

3.        退出線程

void pthread_exit(void *retval);

4.        取消線程

int pthread_cancel(pthread_t thread);

5.        system

         system()會調用fork()產生子進程,由子進程來調用/bin/sh-c string來執行參數string字符串所代表的命令,此命>令執行完後隨即返回原調用的進程。在調用system()期間SIGCHLD 信號會被暫時擱置,SIGINT和SIGQUIT 信號則會被忽略。

         #i nclude<stdlib.h>

         int system(const char *string);

         返回值:

         -1:出現錯誤  

       0:調用成功但是沒有出現子進程  

                >0:成功退出的子進程的id

         參數:

                   String:命令行

內核驅動程序

1.      內核驅動程序主要框架

         內核驅動的開始的函數必須有爲:

                   module_init(function)加載,和module_exit(function)卸載內核。

         內核驅動的函數頭都被定義到linux/或者asm/中。

2.      module_init( x);

driver initialization entry point.

參數:

x      function tobe run at kernel boot time or module insertion

3.      module_exit( x);

driver exit entry point.

參數:

x: function to be runwhen driver is removed

4.      outb()   I/O 上寫入 8 位數據 ( 1 字節 );

inb() 從I/O端口讀取一個字節(即八位)

inw 從I/O端口讀取一個字(即兩個字節,十六位)

outw() I/O 上寫入 16 位數據 ( 2 字節 );

outl () I/O 上寫入 32 位數據 ( 4 字節)。

void outb (unsigned char data, unsigned short port);

byte inb(word port);返回一個字節;

void outw (unsigned short data, unsigned short port);

word inw(word port);返回兩個字節;

void outl (unsigned long data, unsigned short port);

5.       每個設備都對應一個結構體:

struct file_operations {

    struct module *owner;//指向擁有這個模塊的指針,該成員用來在它的操作還在是使用的時候不允許卸載該模塊。

//通常情況下簡單初始化爲THIS_MODULE。

    loff_t (*llseek) (struct file *, loff_t,int); //該操作用來改變當前文件的讀寫位置,並且將新位置作爲返回值。

    ssize_t (*read) (struct file *, char __user*, size_t, loff_t *);//該操作用來從設備中獲取數據。

    ssize_t (*write) (struct file *, const char__user *, size_t, loff_t *);//該操作用來發送數據給設備。

    ssize_t (*aio_read) (struct kiocb *, conststruct iovec *, unsigned long, loff_t); //該操作用來初始化一個異步的讀操作。

    ssize_t (*aio_write) (struct kiocb *, conststruct iovec *, unsigned long, loff_t);//該操作用來初始化一個異步的寫操作。

    int (*readdir) (struct file *, void *,filldir_t);//該操作用來讀取目錄。

    unsigned int (*poll) (struct file *, structpoll_table_struct *);//該操作用來查詢一個或者多個文件描述符的讀或寫是會否堵塞。

    int (*ioctl) (struct inode *, struct file*, unsigned int, unsigned long);//該操作用來提供發出設備特定命令的方法。

    long(*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

    long (*compat_ioctl) (struct file *,unsigned int, unsigned long);

    int (*mmap) (struct file *, structvm_area_struct *);//該操作用來請求將設備內存映射到進程的地址空間。

    int (*open) (struct inode *, struct file*);//該操作用來打開設備文件,也是對設備進行的第一個操作。

    int (*flush) (struct file *, fl_owner_tid);

    int (*release) (struct inode *, struct file*);//該操作用來釋放文件結構。可以爲空。

    int (*fsync) (struct file *, struct dentry*, int datasync);

    int (*aio_fsync) (struct kiocb *, intdatasync);

    int (*fasync) (int, struct file *, int);

    int (*lock) (struct file *, int, structfile_lock *);

    ssize_t (*sendpage) (struct file *, structpage *, int, size_t, loff_t *, int);

    unsigned long (*get_unmapped_area)(structfile *, unsigned long, unsigned long, unsigned long, unsigned long);

    int (*check_flags)(int);

    int (*dir_notify)(struct file *filp,unsigned long arg);

    int (*flock) (struct file *, int, structfile_lock *);

    ssize_t (*splice_write)(structpipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);

    ssize_t (*splice_read)(struct file *,loff_t *, struct pipe_inode_info *, size_t, unsigned int);

    int (*setlease)(struct file *, long, structfile_lock **);

    int (*fsetattr)(struct file *, struct iattr*);

};

6.      將內核數據複製到用戶空間中

unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)

{

if (access_ok(VERIFY_WRITE, to, n))

n = __copy_to_user(to, from, n);

return n;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章