『壹』 在linux系統下實現對system() 函數對fork() ,exec(),waitpid()函數的調用。求大神解答
不知道你這實現這些函數的調用是什麼意思,是要重寫這些介面嗎?還是舉個例子說明?
我解釋一下吧:
(1)system()其實就是對fork()和exec()函數族等的封裝。
(2)fork()是用來產生子進程的,是現在我知道的唯一一個返回兩個值的函數(有過有另外的,麻煩網友指出),返回-1表示執行失敗;否則返回大於0的值時,表示是子進程的進程號,返回0時,表示父進程創建子進程成功。
(3)exec()不是一個函數,是函數族,有execl(),execv(),execle(),execve(),execlp(),execvp(),它們常用於子進程中「脫胎換骨」,就是父進程創建子進程後,子進程幾乎是父進程的拷貝(只有很少的東西不一樣,如進程號(PID)等),然後子進程調用exec()函數族執行其他的程序,即將原來進程的東西全部清除掉,稱為一個嶄新的進程,所以叫「脫胎換骨」。
(4)waitpid()是用在父進程中等待進程退出的,如果父進程不調用這個介面,那麼它有可能先於子進程退出,那麼子進程就會稱為孤兒進程,繼而被init進程(PID為1的進程,Linux啟動後第一個啟動的進程)收養。或者父進程並未退出,也未調用這個介面,但是子進程已經執行完成,那麼子進程就會成為一個僵屍進程。
具體例子在網上找找吧,都不是很難。
『貳』 Linux命令SYSTEM()啟動命令
system是一個使用簡單,設計復雜的程序。
它主要包含fork exec waitpid三個步驟。
下來我來還原樓主的錯誤:
程序A:
/* socksrv.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> /* for struct sockaddr_in*/
#define BACKLOG 10
#define MYPORT 4000
int main()
{
char *addr;
int sockfd;
int new_fd;
struct sockaddr_in my_addr, their_addr;
int res;
int sin_size;
char *buf;
/* 取得套接字描述符*/
sockfd = socket(AF_INET, /* domain*/
SOCK_STREAM, /* type*/
0); /* protocol*/
if (sockfd == -1) {
perror("socket");
exit(1);
}
/* Init sockaddr_in */
my_addr.sin_family = AF_INET; /* 注意: 應使用主機位元組順序*/
my_addr.sin_port = htons(MYPORT); /* 注意: 應使用網路位元組順序*/
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 使用自己的 IP 地址 */
bzero(&(my_addr.sin_zero), 8); /* 結構的其餘的部分須置 0*/
/* 指定一個套接字使用的地址及埠*/
res = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr));
if (res == -1) {
perror("bind");
exit(1);
}
/* 監聽請求, 等待連接*/
res = listen(sockfd,
BACKLOG); /* 未經處理的連接請求隊列可容納的最大數目*/
if (res == -1) {
perror("listen");
exit(1);
}
system("./hello&");
/* 接受對方的連接請求, 建立連接,返回一個新的連接描述符.
* 而第一個套接字描述符仍在你的機器上原來的埠 listen()
*/
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, (void *)&their_addr, &sin_size);
buf = (char *)malloc(255);
if (buf == NULL) {
printf("malloc failed\n");
exit(1);
}
/* 接受對方發來的數據*/
res = recv(new_fd, buf, 255, 0);
if (res == -1) {
perror("recv()");
exit(1);
}
/* 關閉本次連接*/
close(new_fd);
/* 關閉系統監聽*/
close(sockfd);
printf("recv data:%s\n", buf);
free(buf);
return 0;
}
程序B:hello,在主程序中用system("./hello&)調用。
#include <stdlib.h>
int main(){
while(1){
sleep(1000);
}
return 0;
}
編譯後運行程序A。我們可以在其它終端窗口看到 ./A ./hello正在運行,netstat -a 看到,tcp 4000埠被 佔用。
我們用Ctrl+c中斷程序A模擬樓主的崩潰操作。
這時,再在其它終端窗口看看,./A沒有了。./hello還在運行。netstat -a看到。4000埠還在佔用。
這時再次運行./A,提示bind: Address already in use而退出。
情況就是這樣。
因為執行system時,系統會fork一個A的子進程,再去執行B.
當你的A崩潰以後,它的一個子進程實際上還在運行,它打開的埠,文件,等還在使用。
所以再次運行A時,由於自定的互斥機制而退出。
如:再次綁定埠時提示埠已在使用。
殺死B後,A的子進程結束,它的資源釋放,所以才能再次運行A。
我建議樓主使用exec系列函數來啟動B。
『叄』 如何在linux系統下實現添加和刪除應用程序
linux安裝過程中,提供了一個可以選擇要安裝報的界面,使用很方便。
如圖1:
馬上又OK了!
此時查看 /etc/yum.repos.d/update.repo 文件就會發現 enabled = 0
[update]
name=update
baseurl=file:///mnt/Server
gpgcheck=0
enabled = 0
在5.1的系統中無法執行第7步以下的內容,也就是不可以用圖形界面的方式來屏蔽掉Repositories,只能通過更改
配置文件將 enabled = 0 來實現。
『肆』 如何實現一個新的linux系統調用
若要在 kernel 裡面新增加一個自己的 sys call,大致需要這么幾個步驟: a,新增自己 sys call 的代碼,並修改相應 makefile; b,修改相應頭文件,分配自己的系統調用號; c,系統調用通過中斷加查表的方式實現,