关于linux进程编程的一些笔记整理。
$ps -aux (以下是在我的计算机上的运行结果,你的结果很可能与这不同。) USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.1 0.4 1412 520 ? S May15 0:04 init [3] root 2 0.0 0.0 0 0 ? SW May15 0:00 [keventd] root 3 0.0 0.0 0 0 ? SW May15 0:00 [kapm-idled] root 4 0.0 0.0 0 0 ? SWN May15 0:00 [ksoftirqd_CPU0] root 5 0.0 0.0 0 0 ? SW May15 0:00 [kswapd] root 6 0.0 0.0 0 0 ? SW May15 0:00 [kreclaimd] root 7 0.0 0.0 0 0 ? SW May15 0:00 [bdflush] root 8 0.0 0.0 0 0 ? SW May15 0:00 [kupdated] root 9 0.0 0.0 0 0 ? SW< May15 0:00 [mdrecoveryd] root 13 0.0 0.0 0 0 ? SW May15 0:00 [kjournald] root 132 0.0 0.0 0 0 ? SW May15 0:00 [kjournald] root 673 0.0 0.4 1472 592 ? S May15 0:00 syslogd -m 0 root 678 0.0 0.8 2084 1116 ? S May15 0:00 klogd -2 rpc 698 0.0 0.4 1552 588 ? S May15 0:00 portmap rpcuser 726 0.0 0.6 1596 764 ? S May15 0:00 rpc.statd root 839 0.0 0.4 1396 524 ? S May15 0:00 /usr/sbin/apmd -p root 908 0.0 0.7 2264 1000 ? S May15 0:00 xinetd -stayalive root 948 0.0 1.5 5296 1984 ? S May15 0:00 sendmail: accepti root 967 0.0 0.3 1440 484 ? S May15 0:00 gpm -t ps/2 -m /d wnn 987 0.0 2.7 4732 3440 ? S May15 0:00 /usr/bin/cserver root 1005 0.0 0.5 1584 660 ? S May15 0:00 crond wnn 1025 0.0 1.9 3720 2488 ? S May15 0:00 /usr/bin/tserver xfs 1079 0.0 2.5 4592 3216 ? S May15 0:00 xfs -droppriv -da daemon 1115 0.0 0.4 1444 568 ? S May15 0:00 /usr/sbin/atd root 1130 0.0 0.3 1384 448 tty1 S May15 0:00 /sbin/mingetty tt root 1131 0.0 0.3 1384 448 tty2 S May15 0:00 /sbin/mingetty tt root 1132 0.0 0.3 1384 448 tty3 S May15 0:00 /sbin/mingetty tt root 1133 0.0 0.3 1384 448 tty4 S May15 0:00 /sbin/mingetty tt root 1134 0.0 0.3 1384 448 tty5 S May15 0:00 /sbin/mingetty tt root 1135 0.0 0.3 1384 448 tty6 S May15 0:00 /sbin/mingetty tt root 8769 0.0 0.6 1744 812 ? S 00:08 0:00 in.telnetd: 192.1 root 8770 0.0 0.9 2336 1184 pts/0 S 00:08 0:00 login -- lei lei 8771 0.1 0.9 2432 1264 pts/0 S 00:08 0:00 -bash lei 8809 0.0 0.6 2764 808 pts/0 R 00:09 0:00 ps -aux
/* zombie.c */
#include <sys/types.h>
#include <unistd.h>
main()
{
pid_t pid;
pid=fork();
if(pid<0) /*
如果出错 */
printf("error occurred!/n");
else if(pid==0) /*
如果是子进程 */
exit(0);
else /*
如果是父进程 */
sleep(60); /*
休眠60秒,这段时间里,父进程什么也干不了 */
wait(NULL); /*
收集僵尸进程 */
}
|
$ cc zombie.c -o zombie
|
$ ./zombie &
[1] 1577
|
$ ps -ax
... ...
1177 pts/0 S 0:00 -bash
1577 pts/0 S 0:00 ./zombie
1578 pts/0 Z 0:00 [zombie <defunct>]
1579 pts/0 R 0:00 ps -ax
|
#include <sys/types.h> /*
提供类型pid_t的定义 */
#include <sys/wait.h>
pid_t wait(int *status)
|
pid = wait(NULL);
|
/* wait1.c */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
main()
{
pid_t pc,pr;
pc=fork();
if(pc<0) /*
如果出错 */
printf("error ocurred!/n");
else if(pc==0){ /*
如果是子进程 */
printf("This is child process with pid of %d/n",getpid());
sleep(10); /*
睡眠10秒钟 */
}
else{ /*
如果是父进程 */
pr=wait(NULL); /*
在这里等待 */
printf("I catched a child process with pid of %d/n"),pr);
}
exit(0);
}
|
$ cc wait1.c -o wait1
$ ./wait1
This is child process with pid of 1508
I catched a child process with pid of 1508
|
/* wait2.c */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
main()
{
int status;
pid_t pc,pr;
pc=fork();
if(pc<0) /*
如果出错 */
printf("error ocurred!/n");
else if(pc==0){ /*
子进程 */
printf("This is child process with pid of %d./n",getpid());
exit(3); /*
子进程返回3 */
}
else{ /*
父进程 */
pr=wait(&status);
if(WIFEXITED(status)){ /*
如果WIFEXITED返回非零值 */
printf("the child process %d exit normally./n",pr);
printf("the return code is %d./n",WEXITSTATUS(status));
}else /*
如果WIFEXITED返回零 */
printf("the child process %d exit abnormally./n",pr);
}
}
|
$ cc wait2.c -o wait2
$ ./wait2
This is child process with pid of 1538.
the child process 1538 exit normally.
the return code is 3.
|
#include <sys/types.h>
#include <sys/wait.h>
main()
{
pid_t pc, pr;
int status;
pc=fork();
if(pc<0)
printf("Error occured on forking./n");
else if(pc==0){
/*
子进程的工作 */
exit(0);
}else{
/*
父进程的工作 */
pr=wait(&status);
/*
利用子进程的结果 */
}
}
|
#include <sys/types.h> /*
提供类型pid_t的定义 */
#include <sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options)
|
ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);
|
ret=waitpid(-1,NULL,0);
|
static inline pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}
|
/* waitpid.c */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
main()
{
pid_t pc, pr;
pc=fork();
if(pc<0) /*
如果fork出错 */
printf("Error occured on forking./n");
else if(pc==0){ /*
如果是子进程 */
sleep(10); /*
睡眠10秒 */
exit(0);
}
/*
如果是父进程 */
do{
pr=waitpid(pc, NULL, WNOHANG); /*
使用了WNOHANG参数,waitpid不会在这里等待 */
if(pr==0){ /*
如果没有收集到子进程 */
printf("No child exited/n");
sleep(1);
}
}while(pr==0); /*
没有收集到子进程,就回去继续尝试 */
if(pr==pc)
printf("successfully get child %d/n", pr);
else
printf("some error occured/n");
}
|
$ cc waitpid.c -o waitpid
$ ./waitpid
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
successfully get child 1526
|
#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, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
|
int main(int argc, char *argv[], char *envp[])
|
/* main.c */
int main(int argc, char *argv[], char *envp[])
{
printf("/n### ARGC ###/n%d/n", argc);
printf("/n### ARGV ###/n");
while(*argv)
printf("%s/n", *(argv++));
printf("/n### ENVP ###/n");
while(*envp)
printf("%s/n", *(envp++));
return 0;
}
|
$ cc main.c -o main
|
$ ./main -xx 000
### ARGC ###
3
### ARGV ###
./main
-xx
000
### ENVP ###
PWD=/home/lei
REMOTEHOST=dt.laser.com
HOSTNAME=localhost.localdomain
QTDIR=/usr/lib/qt-2.3.1
LESSOPEN=|/usr/bin/lesspipe.sh %s
KDEDIR=/usr
USER=lei
LS_COLORS=
MACHTYPE=i386-redhat-linux-gnu
MAIL=/var/spool/mail/lei
INPUTRC=/etc/inputrc
LANG=en_US
LOGNAME=lei
SHLVL=1
SHELL=/bin/bash
HOSTTYPE=i386
OSTYPE=linux-gnu
HISTSIZE=1000
TERM=ansi
HOME=/home/lei
PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/lei/bin
_=./main
|
int execve(const char *path, char *const argv[], char *const envp[]);
|
/* exec.c */
#include <unistd.h>
main()
{
char *envp[]={"PATH=/tmp",
"USER=lei",
"STATUS=testing",
NULL};
char *argv_execv[]={"echo", "excuted by execv", NULL};
char *argv_execvp[]={"echo", "executed by execvp", NULL};
char *argv_execve[]={"env", NULL};
if(fork()==0)
if(execl("/bin/echo", "echo", "executed by execl", NULL)<0)
perror("Err on execl");
if(fork()==0)
if(execlp("echo", "echo", "executed by execlp", NULL)<0)
perror("Err on execlp");
if(fork()==0)
if(execle("/usr/bin/env", "env", NULL, envp)<0)
perror("Err on execle");
if(fork()==0)
if(execv("/bin/echo", argv_execv)<0)
perror("Err on execv");
if(fork()==0)
if(execvp("echo", argv_execvp)<0)
perror("Err on execvp");
if(fork()==0)
if(execve("/usr/bin/env", argv_execve, envp)<0)
perror("Err on execve");
}
|
$ cc exec.c -o exec
$ ./exec
executed by execl
PATH=/tmp
USER=lei
STATUS=testing
executed by execlp
excuted by execv
executed by execvp
PATH=/tmp
USER=lei
STATUS=testing
|
1: /* mshell.c */
2: #include <sys/types.h>
1: #include <unistd.h>
3: #include <sys/wait.h>
4: #include <string.h>
5: #include <errno.h>
6: #include <stdio.h>
7:
9: void do_cd(char *argv[]);
10: void execute_new(char *argv[]);
11:
12: main()
13: {
14: char *cmd=(void *)malloc(256*sizeof(char));
15: char *cmd_arg[10];
16: int cmdlen,i,j,tag;
17:
18: do{
19: /*
初始化cmd */
20: for(i=0;i<255;i++) cmd[i]='/0';
21:
22: printf("-=Mini Shell=-*| ");
23: fgets(cmd,256,stdin);
24:
25: cmdlen=strlen(cmd);
26: cmdlen--;
27: cmd[cmdlen]='/0';
28:
29
: /* 把命令行分解为指针数组cmd_arg */
30
: for(i=0;i<10;i++) cmd_arg[i]=NULL;
31
: i=0; j=0; tag=0;
32
: while(i<cmdlen && j<10){
33
: if(cmd[i]==' '){
34
: cmd[i]='/0';
35
: tag=0;
36
: }else{
37
: if(tag==0)
38
: cmd_arg[j++]=cmd+i;
39
: tag=1;
40
: }
41
: i++;
42
: }
43
:
44
: /* 如果参数超过10个,就打印错误,并忽略当前输入 */
45
: if(j>=10 && i<cmdlen){
46
: printf("TOO MANY ARGUMENTS/n");
47
: continue;
48
: }
49
:
50
: /* 命令quit:退出Mini Shell */
51
: if(strcmp(cmd_arg[0],"quit")==0)
52
: break;
53
:
54
: /* 命令cd */
55
: if(strcmp(cmd_arg[0],"cd")==0){
56
: do_cd(cmd_arg);
57
: continue;
58
: }
59
:
60
: /* 外部命令或应用程序 */
61
: execute_new(cmd_arg);
62
: }while(1);
63
: }
64
:
65
: /* 实现cd的功能 */
66
: void do_cd(char *argv[])
67
: {
68
: if(argv[1]!=NULL){
69
: if(chdir(argv[1])<0)
70
: switch(errno){
71
: case ENOENT:
72
: printf("DIRECTORY NOT FOUND/n");
73
: break;
74
: case ENOTDIR:
75
: printf("NOT A DIRECTORY NAME/n");
76
: break;
77
: case EACCES:
78
: printf("YOU DO NOT HAVE RIGHT TO ACCESS/n");
79
: break;
80
: default:
81
: printf("SOME ERROR HAPPENED IN CHDIR/n");
82
: }
83
: }
84
:
85
: }
86
:
87
: /* 执行外部命令或应用程序 */
88
: void execute_new(char *argv[])
89
: {
90
: pid_t pid;
91
:
92
: pid=fork();
93
: if(pid<0){
94
: printf("SOME ERROR HAPPENED IN FORK/n");
95
: exit(2);
96
: }else if(pid==0){
97
: if(execvp(argv[0],argv)<0)
98
: switch(errno){
99
: case ENOENT:
100
: printf("COMMAND OR FILENAME NOT FOUND/n");
101
: break;
102
: case EACCES:
103
: printf("YOU DO NOT HAVE RIGHT TO ACCESS/n");
104
: break;
105
: default:
106
: printf("SOME ERROR HAPPENED IN EXEC/n");
107
: }
108
: exit(3);
109
: }else
110
: wait(NULL);
111
: }
|
/* daemon.c */
#include<unistd.h>
#include<sys/types.h>
#include <sys/stat.h>
#define MAXFILE 65535
main()
{
pid_t pid;
int i;
pid=fork();
if(pid<0){
printf("error in fork/n");
exit(1);
}else if(pid>0)
/*
父进程退出 */
exit(0);
/*
调用setsid */
setsid();
/*
切换当前目录 */
chdir("/");
/*
设置文件权限掩码 */
umask(0);
/*
关闭所有可能打开的不需要的文件 */
for(i=0;i<MAXFILE;i++)
close(i);
/*
到现在为止,进程已经成为一个完全的daemon进程,
你可以在这里添加任何你要daemon做的事情,如:
*/
for(;;)
sleep(10);
}
|
#include <unistd.h>
int chdir(const char *path);
|
chdir("/");
|
#include <unistd.h>
pid_t setsid(void);
|
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
|