先買本LINUX入門書開始看吧,至少要了解一些常用的命令和用VI編輯器寫腳本。推薦鳥哥的私房菜,比較不錯的一本LINUX入門書,然後開始學習C語言,至於如何學習C語言,呵呵,無非就是看書,看視頻,自己寫程序,然後不動再看書,看視頻,自己寫程序,當然,遇到問題可以GOOGLE,網路,實在找不到答案可以去一些LINUX的專業論壇提問
2. Linux C語言編程題
把子進程里的close刪掉,父子進程是共享fd的,子進程刪了,父進程怎麼用
3. 求助一道linux C語言編程題
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#define maxsize 20
int main(int argc,char *argv[])
{
int m,n,fd1,fd2;
char s[maxsize];
if(argc==4&&(*++argv)[0]=='-'&&*++*argv=='r'&&*++*argv=='i')
if((fd1=open(*++argv,O_RDONLY))>0&&(fd2=open(*++argv,O_WRONLY))>0)
while((n=read(fd1,s,maxsize))>0)
if(write(fd2,s,n)==n&&lseek(fd2,0,SEEK_CUR)!=-1);
else
printf("write error");
else
printf("open error");
if(n<0)
printf("read error");
return 0;
}
呵呵,利用空餘時間,我只能按字面意思編程(你是從哪弄的啊)
不懂的可以發信息^_^
4. 在Linux下用C語言編程
4。守護進程的創建
如果你在DOS時代編寫過程序,那麼你也許知道在DOS下為了編寫一個常駐內存的程序我們要編寫多少代碼了.相反如果在Linux下編寫一個"常駐內存"的程序卻是很容易的.我們只要幾行代碼就可以做到. 實際上由於Linux是多任務操作系統,我們就是不編寫代碼也可以把一個程序放到後台去執行的.我們只要在命令後面加上&符號SHELL就會把我們的程序放到後台去運行的. 這里我們"開發"一個後台檢查郵件的程序.這個程序每個一個指定的時間回去檢查我們的郵箱,如果發現我們有郵件了,會不斷的報警(通過機箱上的小喇叭來發出聲音). 後面有這個函數的加強版本加強版本
後台進程的創建思想: 首先父進程創建一個子進程.然後子進程殺死父進程(是不是很無情?). 信號處理所有的工作由子進程來處理.
#include
#include
#include
#include
#include
#include
#include
/* Linux 的默任個人的郵箱地址是 /var/spool/mail/用戶的登錄名 */
#define MAIL "/var/spool/mail/hoyt"
/* 睡眠10秒鍾 */
#define SLEEP_TIME 10
main(void)
{
pid_t child;
if((child=fork())==-1)
{
printf("Fork Error:%s\n",strerror(errno));
exit(1);
}
else if(child>0)
while(1);
if(kill(getppid(),SIGTERM)==-1)
{
printf("Kill Parent Error:%s\n",strerror(errno));
exit(1);
}
{
int mailfd;
while(1)
{
if((mailfd=open(MAIL,O_RDONLY))!=-1)
{
fprintf(stderr,"%s","\007");
close(mailfd);
}
sleep(SLEEP_TIME);
}
}
}
你可以在默認的路徑下創建你的郵箱文件,然後測試一下這個程序.當然這個程序還有很多地方要改善的.我們後面會對這個小程序改善的,再看我的改善之前你可以嘗試自己改善一下.比如讓用戶指定郵相的路徑和睡眠時間等等.相信自己可以做到的.動手吧,勇敢的探險者.
好了進程一節的內容我們就先學到這里了.進程是一個非常重要的概念,許多的程序都會用子進程.創建一個子進程是每一個程序員的基本要求!
5. linux c編程
/*
Name: list.c
Author: guozan _SCS_BUPT
Mail: [email protected]
Date: 2010/4/6
實驗目的:練習vi,使用UNIX的系統調用和庫函數,體會UNIX文件通配符的處理方式以及命令對選項的處理方式。
編程實現程序list.c,列表普通磁碟文件(不考慮目錄和設備文件等),列出文件名和文件大小。
與ls命令類似,命令行參數可以有0到多個
0個參數:列出當前目錄下所有文件
參數為普通文件:列出文件
參數為目錄:列出目錄下所有文件
實現自定義選項r,a,l,h,m以及--
r 遞歸方式列出子目錄
a 列出文件名第一個字元為圓點的普通文件(默認情況下不列出文件名首字元為圓點的文件)
l 後跟一整數,限定文件大小的最小值(位元組)
h 後跟一整數,限定文件大小的最大值(位元組)
m 後跟一整數n,限定文件的最近修改時間必須在n天內
-- 顯式地終止命令選項分析
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
/*
slective options about ls
rflag is about recursive
aflag is about ones with . infront
lflag is about the minimum size
hflag is about the maximum size
mflag is about the modified time
*/
int rflag, aflag, lflag, hflag, mflag;
long modified_time; //the last time file be modified, days ago
off_t lower_size; //file's minimum size
off_t upper_size; //file's maximum size
/*
set the flags, thus the ls option
*/
void getoptions(int argc, char *argv[])
{
char ch;
//clear, all unseted
rflag = 0; aflag = 0; lflag = 0; hflag = 0; mflag = 0;
//use getopt to get the options, want to know more, call man
//the last one or after -- was set in argv[optind]
while ((ch = getopt(argc, argv, "ral:h:m:")) != -1) {
switch (ch) {
case 'r': rflag = 1; break;
case 'a': aflag = 1; break;
case 'l': lflag = 1; lower_size = atol(optarg); break;
case 'h': hflag = 1; upper_size = atol(optarg); break;
case 'm': mflag = 1; modified_time = atol(optarg); break; //get days
case '?': printf("Unknown option: %c\n", (char)optopt); break;
default : printf("Step into default\n"); break;
}
}
}
/*
the function to list things in path
*/
int ls(char *path)
{
struct stat st; //for check this is a directory or file
char temp[100]; //if path is null, it is used to get current directory
// get the path
if (path == NULL || path[0] == '-') {
path = temp;
getcwd(path, 100);
}
/* open the inode of file */
if (lstat(path, &st)) {
fprintf(stderr, "Error: %s not exist.\n", path);
return (-1);
}
/* judge whether the file is a file or a directory */
if (S_ISDIR(st.st_mode)) {
ls_dir(path);
}
else if (S_ISREG(st.st_mode)) {
print(path);
}
else {
printf("Not ordinary file, wouldn't be listed.\n");
}
return 0;
}
/*
list dirs, may recursively or not, depending on rflag
one thing is sure that it will list directories and files first,
then consider the things in the directories
*/
int ls_dir(char *path)
{
DIR *dp = NULL;
struct dirent *dirp = NULL;
if (path[0] != '.' || (path[0] == '.' && aflag == 1)) {
printf("\n%s:\n****************************************\n", path);
/* open the directory */
if ((dp = opendir(path)) == NULL) {
fprintf(stderr, "Error: can't open directory %s!\n", path);
return (-1);
}
chdir(path);
/* list all the things in directory */
while ((dirp = readdir(dp)) != NULL) {
print(dirp->d_name);
}
/* recursively ls dirs, after ls things together,
it's time to list things in children directory */
if (rflag == 1) {
rewinddir(dp); //reset dp
while ((dirp = readdir(dp)) != NULL) {
if (strcmp(dirp->d_name, ".") == 0
|| strcmp(dirp->d_name, "..") == 0) { //no current and parent directory
continue;
}
ls_dir_r(dirp->d_name); //only list directories, judged inside the function
}
}
/* close the directory */
if (closedir(dp)) {
fprintf(stderr, "Error: can't close the directory %s!\n", path);
return -1;
}
chdir("..");
}
return 0;
}
/*
list directories recursively,
only directories, nomatter what path you put in
*/
int ls_dir_r(char *path)
{
struct stat st;
/* open the inode of file */
if (lstat(path, &st)) {
fprintf(stderr, "Error: %s not exist.\n", path);
return (-1);
}
/* only ls directories */
if (S_ISDIR(st.st_mode)) {
ls_dir(path);
}
}
/*
print the filetype/size/name on the screen
*/
int print(char *path)
{
struct stat st;
time_t tp;
char *filename = NULL;
//get current time
time(&tp);
if (lstat(path, &st)) {
fprintf(stderr, "Error: %s can't be opened.\n", path);
return (-1);
}
/* get file name */
if ((filename = strrchr(path, '/')) != NULL) {
filename++;
}
else {
filename = path;
}
/* judge whether to list the file */
if ((S_ISDIR(st.st_mode)|| S_ISREG(st.st_mode)) //only directories and normal files
&& (lflag == 0 || (lflag == 1 && (st.st_size >= lower_size))) //the min size
&& (hflag == 0 || (hflag == 1 && (st.st_size <= upper_size))) //the max size
&& (mflag == 0 || (mflag == 1 && ((tp - st.st_mtime) <= modified_time * 24 * 60 * 60))) //modified time
&& (aflag == 1 || (aflag == 0 && filename[0] != '.')) //file with a '.' infront
) {
printf("%s\t%10ld\t%s\n", (S_ISDIR(st.st_mode) ? "DIR": "FILE"), st.st_size, filename);
}
return 0;
}
/*
The main function
*/
int main(int argc, char *argv[])
{
getoptions(argc, argv);
ls(argv[optind]);
return 0;
}
6. Linux 下C語言編程題!
1.#include<stdio.h>
#include<string.h>
#include<malloc.h>
main()
{ char *s,*h,*t;int l;
s=(char*)malloc(20*sizeof(char));
printf("input a string:");
scanf("%s",s);
l=strlen(s);/*求字元串長度賦給l*/
h=s;t=s+l-1; /*h指針指向第一個字元,t指向最後一個*/
for(;h<t;h++,t--) /*從頭尾向中比較*/
{if((*h)!=(*t)){printf("not symmetric");break;} /*發現不同的字元,顯示不對稱,並結束比較*/
}if(h>=t)printf("symmetric"); /*如果比較完了,則顯示對稱*/
getch();
}
2.#include<stdio.h>
#include<string.h>
#include<malloc.h>
main()
{ char *s,*p,*q;
s=(char*)malloc(20*sizeof(char));
printf("input string:");
scanf("%s",s);
p=s;
while(*p)
{if(*p=='a'||*p=='e'||*p=='i'||*p=='o'
||*p=='u')
{q=p;/*讓q指針和q指針指向同一個字元*/
while(*q)
{*q=*(q+1);q++;} /*將當前字元後面的字元前移,相當於把p指著的當前字元刪除*/
p--;}
p++;}
printf("%s",s);
getch();
}
3.#include<stdio.h>
#include<string.h>
main()
{ int a,i=0,s=0;char b[52],c[100],t;
for(t='A';t<='Z';t++)
b[i++]=t;
for(t='a';t<='z';t++)
b[i++]=t;
for(i=0;i<52;i++)
printf("%c",b[i]);/*將52個大小寫字母存入數組b中*/
srand(time(NULL)); /*使每次隨機產生的數不同*/
for(i=0;i<100;i++) /*循環100次,產生100個隨機字母*/
{ a=rand()%51; /*每次從0到51中產生一個隨機數,從而從b〔0〕到b〔51〕中選出一個字母*/
c[i]=b[a]; /*每次產生的隨機字母存入數組c中*/
if(b[a]=='a'||b[a]=='e'||b[a]=='i'||
b[a]=='o'||b[a]=='u'||b[a]=='A'||
b[a]=='E'||b[a]=='I'||b[a]=='O'||b[a]
=='U')s++; /*當是母音字母時,用s來統計個數*/
}
printf("\n");
for(i=0;i<100;i++)printf("%c ",c[i]);
printf("\ns:%d",s);
getch();
}
7. 想從事Linux下C編程,我應該都學些什麼
C語言程序設計
LINUX操作系統
LINUX程序設計
SHELL程序設計
8. LinuxC編程一站式學習的目 錄
上篇 C語言入門
第1章 程序的基本概念 2
1.1 程序和編程語言 2
1.2 自然語言和形式語言 6
1.3 程序的調試 7
1.4 第一個程序 9
第2章 常量、變數和表達式 12
2.1 繼續Hello World 12
2.2 常量 15
2.3 變數 16
2.4 賦值 18
2.5 表達式 19
2.6 字元類型與字元編碼 23
第3章 簡單函數 24
3.1 數學函數 24
3.2 自定義函數 26
3.3 形參和實參 31
3.4 全局變數、局部變數和作用域 35
第4章 分支語句 41
4.1 if語句 41
4.2 if/else語句 43
4.3 布爾代數 45
4.4 switch語句 49
第5章 深入理解函數 51
5.1 return語句 51
5.2 增量式開發 54
5.3 遞歸 58
第6章 循環語句 64
6.1 while語句 64
6.2 do/while語句 66
6.3 for語句 67
6.4 break和continue語句 69
6.5 嵌套循環 70
6.6 goto語句和標號 71
第7章 結構體 74
7.1 復合類型與結構體 74
7.2 數據抽象 78
7.3 數據類型標志 82
7.4 嵌套結構體 84
第8章 數組 85
8.1 數組的基本概念 85
8.2 數組應用實例:統計隨機數 88
8.3 數組應用實例:直方圖 91
8.4 字元串 94
8.5 多維數組 95
第9章 編碼風格 100
9.1 縮進和空白 100
9.2 注釋 104
9.3 標識符命名 107
9.4 函數 108
9.5 indent工具 108
第10章 gdb 110
10.1 單步執行和跟蹤函數調用 110
10.2 斷點 117
10.3 觀察點 121
10.4 段錯誤 125
第11章 排序與查找 128
11.1 演算法的概念 128
11.2 插入排序 129
11.3 演算法的時間復雜度分析 131
11.4 歸並排序 133
11.5 線性查找 138
11.6 折半查找 139
第12章 棧與隊列 144
12.1 數據結構的概念 144
12.2 堆棧 144
12.3 深度優先搜索 146
12.4 隊列與廣度優先搜索 152
12.5 環形隊列 156
本階段總結 159
下篇 C語言本質
第13章 計算機中數的表示 162
13.1 為什麼計算機用二進制計數 162
13.2 不同進制之間的換算 164
13.3 整數的加減運算 165
13.3.1 Sign and Magnitude表示法 165
13.3.2 1's Complement表示法 166
13.3.3 2's Complement表示法 167
13.3.4 有符號數和無符號數 168
13.4 浮點數 169
第14章 數據類型詳解 172
14.1 整型 172
14.2 浮點型 176
14.3 類型轉換 177
14.3.1 Integer Promotion 177
14.3.2 Usual Arithmetic Conversion 178
14.3.3 由賦值產生的類型轉換 179
14.3.4 強制類型轉換 179
14.3.5 編譯器如何處理類型轉換 179
第15章 運算符詳解 182
15.1 位運算 182
15.1.1 按位與、或、異或、取反運算 182
15.1.2 移位運算 183
15.1.3 掩碼 184
15.1.4 異或運算的一些特性 185
15.2 其他運算符 186
15.2.1 復合賦值運算符 186
15.2.2 條件運算符 186
15.2.3 逗號運算符 187
15.2.4 sizeof運算符與typedef類型聲明 187
15.3 Side Effect與Sequence Point 189
15.4 運算符總結 191
第16章 計算機體系結構基礎 193
16.1 內存與地址 193
16.2 CPU 193
16.3 設備 196
16.4 MMU 198
16.5 Memory Hierarchy 201
第17章 x86匯編程序基礎 205
17.1 最簡單的匯編程序 205
17.2 x86的寄存器 208
17.3 第二個匯編程序 209
17.4 定址方式 211
17.5 ELF文件 212
17.5.1 目標文件 213
17.5.2 可執行文件 218
第18章 匯編與C之間的關系 224
18.1 函數調用 224
18.2 main函數、啟動常式和退出狀態 230
18.3 變數的存儲布局 237
18.4 結構體和聯合體 244
18.5 C內聯匯編 248
18.6 volatile限定符 250
第19章 鏈接詳解 255
19.1 多目標文件的鏈接 255
19.2 定義和聲明 260
19.2.1 extern和static關鍵字 260
19.2.2 頭文件 264
19.2.3 定義和聲明的詳細規則 268
19.3 靜態庫 271
19.4 共享庫 274
19.4.1 編譯、鏈接、運行 274
19.4.2 函數的動態鏈接過程 281
19.4.3 共享庫的命名慣例 282
19.5 虛擬內存管理 284
第20章 預處理 290
20.1 預處理的步驟 290
20.2 宏定義 291
20.2.1 函數式宏定義 291
20.2.2 內聯函數 294
20.2.3 #、##運算符和可變參數 296
20.2.4 #undef預處理指示 298
20.2.5 宏展開的步驟 299
20.3 條件預處理指示 300
20.4 其他預處理特性 303
第21章 Makefile基礎 306
21.1 基本規則 306
21.2 隱含規則和模式規則 313
21.3 變數 317
21.4 自動處理頭文件的依賴關系 321
21.5 常用的make命令行選項 324
第22章 指針 327
22.1 指針的基本概念 327
22.2 指針類型的參數和返回值 331
22.3 指針與數組 332
22.4 指針與const限定符 335
22.5 指針與結構體 337
22.6 指向指針的指針與指針數組 337
22.7 指向數組的指針與多維數組 340
22.8 函數類型和函數指針類型 341
22.9 不完全類型和復雜聲明 344
第23章 函數介面 349
23.1 本章的預備知識 349
23.1.1 strcpy與strncpy 349
23.1.2 malloc與free 354
23.2 傳入參數與傳出參數 358
23.3 兩層指針的參數 360
23.4 返回值是指針的情況 362
23.5 回調函數 365
23.6 可變參數 368
第24章 C標准庫 372
24.1 字元串操作函數 373
24.1.1 給字元串賦初值 373
24.1.2 取字元串的長度 374
24.1.3 拷貝字元串 375
24.1.4 連接字元串 377
24.1.5 比較字元串 378
24.1.6 搜索字元串 379
24.1.7 分割字元串 380
24.2 標准I/O庫函數 383
24.2.1 文件的基本概念 383
24.2.2 fopen/fclose 384
24.2.3 stdin/stdout/stderr 387
24.2.4 errno與perror/strerror函數 388
24.2.5 以位元組為單位的I/O函數 391
24.2.6 操作讀寫位置的函數 393
24.2.7 以字元串為單位的I/O函數 395
24.2.8 以記錄為單位的I/O函數 397
24.2.9 格式化I/O函數 399
24.2.10 C標准庫的I/O緩沖區 406
24.2.11 本節綜合練習 410
24.3 數值字元串轉換函數 412
24.4 分配內存的函數 414
第25章 鏈表、二叉樹和哈希表 415
25.1 鏈表 415
25.1.1 單鏈表 415
25.1.2 雙向鏈表 421
25.1.3 靜態鏈表 425
25.1.4 本節綜合練習 426
25.2 二叉樹 426
25.2.1 二叉樹的基本概念 426
25.2.2 排序二叉樹 432
25.3 哈希表 437
本階段總結 439
附錄A 字元編碼 442
索引 449
參考書目 474
9. linux操作系統上c語言編程入門怎麼解決
Linux程序設計入門--進程介紹
Linux下進程的創建
前言:
這篇文章是用來介紹在Linux下和進程相關的各個概念.我們將會學到:
進程的概念
進程的身份
進程的創建
守護進程的創建
----------------------------------------
----
1。進程的概念
Linux操作系統是面向多用戶的.在同一時間可以有許多用戶向操作系統發出各種命
令.那麼操作系統是怎麼實現多用戶的環境呢? 在現代的操作系統裡面,都有程序和進程
的概念.那麼什麼是程序,什麼是進程呢? 通俗的講程序是一個包含可以執行代碼的文件
,是一個靜態的文件.而進程是一個開始執行但是還沒有結束的程序的實例.就是可執行文
件的具體實現. 一個程序可能有許多進程,而每一個進程又可以有許多子進程.依次循環
下去,而產生子孫進程. 當程序被系統調用到內存以後,系統會給程序分配一定的資源(內
存,設備等等)然後進行一系列的復雜操作,使程序變成進程以供系統調用.在系統裡面只
有進程沒有程序,為了區分各個不同的進程,系統給每一個進程分配了一個ID(就象我們的
身份證)以便識別. 為了充分的利用資源,系統還對進程區分了不同的狀態.將進程分為新
建,運行,阻塞,就緒和完成五個狀態. 新建表示進程正在被創建,運行是進程正在運行,阻
塞是進程正在等待某一個事件發生,就緒是表示系統正在等待CPU來執行命令,而完成表示
進程已經結束了系統正在回收資源. 關於進程五個狀態的詳細解說我們可以看《操作系
統》上面有詳細的解說。
2。進程的標志
上面我們知道了進程都有一個ID,那麼我們怎麼得到進程的ID呢?系統調用getpid可
以得到進程的ID,而getppid可以得到父進程(創建調用該函數進程的進程)的ID.
#include <unistd>
pid_t getpid(void);
pid_t getppid(void);
進程是為程序服務的,而程序是為了用戶服務的.系統為了找到進程的用戶名,還為進程和
用戶建立聯系.這個用戶稱為進程的所有者.相應的每一個用戶也有一個用戶ID.通過系統
調用getuid可以得到進程的所有者的ID.由於進程要用到一些資源,而Linux對系統資源是
進行保護的,為了獲取一定資源進程還有一個有效用戶ID.這個ID和系統的資源使用有關
,涉及到進程的許可權. 通過系統調用geteuid我們可以得到進程的有效用戶ID. 和用戶ID
相對應進程還有一個組ID和有效組ID系統調用getgid和getegid可以分別得到組ID和有效
組ID
#include <unistd>
#include <sys/types.h>
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
git_t getegid(void);
有時候我們還會對用戶的其他信息感興趣(登錄名等等),這個時候我們可以調用getpwui
d來得到.
struct passwd {
char *pw_name; /* 登錄名稱 */
char *pw_passwd; /* 登錄口令 */
uid_t pw_uid; /* 用戶ID */
gid_t pw_gid; /* 用戶組ID */
char *pw_gecos; /* 用戶的真名 */
char *pw_dir; /* 用戶的目錄 */
char *pw_shell; /* 用戶的SHELL */
};
#include <pwd.h>
#include <sys/types.h>
struct passwd *getpwuid(uid_t uid);
下面我們學習一個實例來實踐一下上面我們所學習的幾個函數:
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc,char **argv)
{
pid_t my_pid,parent_pid;
uid_t my_uid,my_euid;
gid_t my_gid,my_egid;
struct passwd *my_info;
my_pid=getpid();
parent_pid=getppid();
my_uid=getuid();
my_euid=geteuid();
my_gid=getgid();
my_egid=getegid();
my_info=getpwuid(my_uid);
printf("Process ID:%ld/n",my_pid);
printf("Parent ID:%ld/n",parent_pid);
printf("User ID:%ld/n",my_uid);
printf("Effective User ID:%ld/n",my_euid);
printf("Group ID:%ld/n",my_gid);
printf("Effective Group ID:%ld/n",my_egid):
if(my_info)
{
printf("My Login Name:%s/n" ,my_info->pw_name);
printf("My Password :%s/n" ,my_info->pw_passwd);
printf("My User ID :%ld/n",my_info->pw_uid);
printf("My Group ID :%ld/n",my_info->pw_gid);
printf("My Real Name:%s/n" ,my_info->pw_gecos);
printf("My Home Dir :%s/n", my_info->pw_dir);
printf("My Work Shell:%s/n", my_info->pw_shell);
}
}
3。進程的創建
創建一個進程的系統調用很簡單.我們只要調用fork函數就可以了.
#include <unistd.h>
pid_t fork();
當一個進程調用了fork以後,系統會創建一個子進程.這個子進程和父進程不同的地方只
有他的進程ID和父進程ID,其他的都是一樣.就象符進程克隆(clone)自己一樣.當然創建
兩個一模一樣的進程是沒有意義的.為了區分父進程和子進程,我們必須跟蹤fork的返回
值. 當fork掉用失敗的時候(內存不足或者是用戶的最大進程數已到)fork返回-1,否則f
ork的返回值有重要的作用.對於父進程fork返回子進程的ID,而對於fork子進程返回0.我
們就是根據這個返回值來區分父子進程的. 父進程為什麼要創建子進程呢?前面我們已經
說過了Linux是一個多用戶操作系統,在同一時間會有許多的用戶在爭奪系統的資源.有時
進程為了早一點完成任務就創建子進程來爭奪資源. 一旦子進程被創建,父子進程一起從
fork處繼續執行,相互競爭系統的資源.有時候我們希望子進程繼續執行,而父進程阻塞直
到子進程完成任務.這個時候我們可以調用wait或者waitpid系統調用.
#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);
wait系統調用會使父進程阻塞直到一個子進程結束或者是父進程接受到了一個信號.如果
沒有父進程沒有子進程或者他的子進程已經結束了wait回立即返回.成功時(因一個子進
程結束)wait將返回子進程的ID,否則返回-1,並設置全局變數errno.stat_loc是子進程的
退出狀態.子進程調用exit,_exit 或者是return來設置這個值. 為了得到這個值Linux定
義了幾個宏來測試這個返回值.
WIFEXITED:判斷子進程退出值是非0
WEXITSTATUS:判斷子進程的退出值(當子進程退出時非0).
WIFSIGNALED:子進程由於有沒有獲得的信號而退出.
WTERMSIG:子進程沒有獲得的信號號(在WIFSIGNALED為真時才有意義).
waitpid等待指定的子進程直到子進程返回.如果pid為正值則等待指定的進程(pid).如果
為0則等待任何一個組ID和調用者的組ID相同的進程.為-1時等同於wait調用.小於-1時等
待任何一個組ID等於pid絕對值的進程. stat_loc和wait的意義一樣. options可以決定
父進程的狀態.可以取兩個值 WNOHANG:父進程立即返回當沒有子進程存在時. WUNTACHE
D:當子進程結束時waitpid返回,但是子進程的退出狀態不可得到.
父進程創建子進程後,子進程一般要執行不同的程序.為了調用系統程序,我們可以使用系
統調用exec族調用.exec族調用有著5個函數.
#include <unistd.h>
int execl(const char *path,const char *arg,...);
int execlp(const char *file,const char *arg,...);
int execle(const char *path,const char *arg,...);
int execv(const char *path,char *const argv[]);
int execvp(const char *file,char *const argv[]):
exec族調用可以執行給定程序.關於exec族調用的詳細解說可以參考系統手冊(man exec
l). 下面我們來學習一個實例.注意編譯的時候要加 -lm以便連接數學函數庫.
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>
void main(void)
{
pid_t child;
int status;
printf("This will demostrate how to get child status/n");
if((child=fork())==-1)
{
printf("Fork Error :%s/n",strerror(errno));
exit(1);
}
else if(child==0)
{
int i;
printf("I am the child:%ld/n",getpid());
for(i=0;i<1000000;i++) sin(i);
i=5;
printf("I exit with %d/n",i);
exit(i);
}
while(((child=wait(&status))==-1)&(errno==EINTR));
if(child==-1)
printf("Wait Error:%s/n",strerror(errno));
else if(!status)
printf("Child %ld terminated normally return status is zero/n",
child);
else if(WIFEXITED(status))
printf("Child %ld terminated normally return status is %d/n",
child,WEXITSTATUS(status));
else if(WIFSIGNALED(status))
printf("Child %ld terminated e to signal %d znot caught/n",
child,WTERMSIG(status));
}
strerror函數會返回一個指定的錯誤號的錯誤信息的字元串.
4。守護進程的創建
如果你在DOS時代編寫過程序,那麼你也許知道在DOS下為了編寫一個常駐內存的程序
我們要編寫多少代碼了.相反如果在Linux下編寫一個"常駐內存"的程序卻是很容易的.我
們只要幾行代碼就可以做到. 實際上由於Linux是多任務操作系統,我們就是不編寫代碼
也可以把一個程序放到後台去執行的.我們只要在命令後面加上&符號SHELL就會把我們的
程序放到後台去運行的. 這里我們"開發"一個後台檢查郵件的程序.這個程序每個一個指
定的時間回去檢查我們的郵箱,如果發現我們有郵件了,會不斷的報警(通過機箱上的小喇
叭來發出聲音). 後面有這個函數的加強版本加強版本
後台進程的創建思想: 首先父進程創建一個子進程.然後子進程殺死父進程(是不是很無
情?). 信號處理所有的工作由子進程來處理.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
/* Linux 的默任個人的郵箱地址是 /var/spool/mail/用戶的登錄名 */
#define MAIL "/var/spool/mail/hoyt"
/* 睡眠10秒鍾 */
#define SLEEP_TIME 10
main(void)
{
pid_t child;
if((child=fork())==-1)
{
printf("Fork Error:%s/n",strerror(errno));
exit(1);
}
else if(child>0)
while(1);
if(kill(getppid(),SIGTERM)==-1)
{
printf("Kill Parent Error:%s/n",strerror(errno));
exit(1);
}
{
int mailfd;
while(1)
{
if((mailfd=open(MAIL,O_RDONLY))!=-1)
{
fprintf(stderr,"%s","7");
close(mailfd);
}
sleep(SLEEP_TIME);
}
}
}
你可以在默認的路徑下創建你的郵箱文件,然後測試一下這個程序.當然這個程序還有很
多地方要改善的.我們後面會對這個小程序改善的,再看我的改善之前你可以嘗試自己改
善一下.比如讓用戶指定郵相的路徑和睡眠時間等等.相信自己可以做到的.動手吧,勇敢
的探險者.
好了進程一節的內容我們就先學到這里了.進程是一個非常重要的概念,許多的程序都會
用子進程.創建一個子進程是每一個程序員的基本要求!
10. linux下c應該怎麼學,新手
這個問題應該分成2問,也就是說學習過程應該分成相應的兩步:
1、C言語如何學習;2、如何在linux下編譯C程序。
第一個問題簡單說來就是好的入門教程+高級教程+經典實例練習,入門教程是前提,如果什麼都不知道的話無論是在linux下還是其他系統下都是一片茫然;
第二個問題簡單說來就是學會gcc,gdb,make,makefile的用法,這個比較容易,在C言語入門教程學完後花很少時間熟悉一下就會用了。