├── Chapter02 ├── .while_control.sh.swp ├── 1_tmp ├── 2_tmp ├── AND_list.sh ├── CD_program │ ├── cd_db.sh │ ├── title.cdb │ └── tracks.cdb ├── OR_list.sh ├── \ ├── _1.txt ├── a_simple_function.sh ├── a_text_file ├── bill.c ├── bill.o ├── break_command.sh ├── case_control.sh ├── case_control_2.sh ├── case_control_3.sh ├── colon_command.sh ├── command_executive.sh ├── continue_command.sh ├── elif_condition.sh ├── exit_command.sh ├── export1_command.sh ├── export2_command.sh ├── first ├── for_control.sh ├── for_control_*.sh ├── giftojpeg.sh ├── hello ├── hello.c ├── here_document_with_ed.sh ├── herw_command.sh ├── if_condition ├── jpg ├── lib.h ├── libfoo.a ├── local_global_variable.sh ├── math_expand.sh ├── parameter_expand.sh ├── program ├── program.c ├── program.o ├── questions.sh ├── return_from_function.sh ├── set_command.sh ├── shift_command.sh ├── signal_process.sh ├── test.gif ├── test.jpg ├── test_command ├── try_var ├── unset_command.sh ├── until_control.sh ├── variable ├── while_control.sh └── words2.txt ├── Chapter03 ├── copy_block ├── copy_block.c ├── copy_stdio ├── copy_stdio.c ├── copy_system ├── copy_system.c ├── draft1.txt ├── file.in ├── file.out ├── mmap ├── mmap.c ├── printdir ├── printdir.c ├── records.dat ├── simple_read ├── simple_read.c ├── simple_write └── simple_write.c ├── Chapter04 ├── argopt ├── argopt.c ├── args ├── args.c ├── ctime ├── ctime.c ├── environ ├── environ.c ├── envtime ├── envtime.c ├── gmtime ├── gmtime.c ├── hostget ├── hostget.c ├── limits ├── limits.c ├── logmask ├── logmask.c ├── longopt ├── longopt.c ├── showenv ├── showenv.c ├── strftime ├── strftime.c ├── syslog ├── syslog.c ├── tmpnam ├── tmpnam.c ├── user └── user.c ├── Chapter05 ├── badterm ├── badterm.c ├── file ├── file.error ├── kbhit ├── kbhit.c ├── menu1 ├── menu1.c ├── menu2 ├── menu2.c ├── menu3 ├── menu3.c ├── menu4 ├── menu4.c ├── menu5 ├── menu5.c ├── password ├── password.c ├── sizeterm └── sizeterm.c ├── Chapter06 ├── CD_APP │ ├── curses_cd │ ├── curses_cd.c │ ├── title.cdb │ └── tracks.cdb ├── color ├── color.c ├── ipmode ├── ipmode.c ├── keypad ├── keypad.c ├── moveadd ├── moveadd.c ├── multiw1 ├── multiw1.c ├── pad ├── pad.c ├── screen1 ├── screen1.c ├── subsc1 └── subsc1.c ├── Chapter07 ├── CD_APP │ ├── Makefile │ ├── app_ui.c │ ├── app_ui.o │ ├── application │ ├── cd_access.c │ ├── cd_access.o │ ├── cd_data.h │ ├── cdc_data.dir │ ├── cdc_data.pag │ ├── cdt_data.dir │ └── cdt_data.pag ├── dbm1 ├── dbm1.c ├── dbm2 ├── dbm2.c ├── lock1 ├── lock1.c ├── lock2 ├── lock2.c ├── lock3 ├── lock3.c ├── lock4 ├── lock4.c ├── lock5 ├── lock5.c ├── memory1 ├── memory1.c ├── memory2 ├── memory2.c ├── memory3 ├── memory3.c ├── memory4 ├── memory4.c ├── memory5a ├── memory5a.c ├── memory5b ├── memory5b.c ├── memory6 └── memory6.c ├── Chapter08 ├── connect1 ├── connect1.c ├── connect2 ├── connect2.c ├── create_children.sql ├── insert1 ├── insert1.c ├── insert2 ├── insert2.c ├── select1 ├── select1.c ├── select2 ├── select2.c ├── select3 ├── select3.c ├── select4 ├── select4.c ├── update1 └── update1.c ├── Chapter09 ├── 2.c ├── 2.o ├── 3.c ├── 3.o ├── Makefile1 ├── Makefile2 ├── Makefile3 ├── Makefile5 ├── Makefile6 ├── RCS │ └── important.c,v ├── a.h ├── b.h ├── c.h ├── cvs-sp │ ├── Makefile │ ├── hello.c │ └── junk │ │ └── neuqsc │ │ ├── CVS │ │ ├── Entries │ │ ├── Entries.Log │ │ ├── Entries.Static │ │ ├── Repository │ │ └── Root │ │ └── chap9-cvs │ │ ├── CVS │ │ ├── Entries │ │ ├── Repository │ │ └── Root │ │ ├── Makefile │ │ ├── hello │ │ └── hello.c ├── diffs ├── file1 ├── file2 ├── foo.c ├── main.c ├── main.o ├── myapp ├── myapp-1.0.tar.gz ├── myapp-1.0 │ ├── 2.c │ ├── 3.c │ ├── Makefile6 │ ├── a.h │ ├── b.h │ ├── c.h │ ├── foo.c │ ├── main.c │ └── myapp.1 ├── myapp.1 └── mylib.a ├── Chapter10 ├── ├── assert ├── assert.c ├── checker ├── checker.c ├── cinfo ├── cinfo.c ├── debug0.c ├── debug1 ├── debug1.c ├── debug2 ├── debug2.c ├── debug3 ├── debug3.c ├── debug4 ├── debug4.c ├── efence.c ├── gmon.out └── tmp ├── Chapter11 ├── alarm ├── alarm.c ├── ctrlc ├── ctrlc.c ├── ctrlc2 ├── ctrlc2.c ├── execlp ├── execlp.c ├── file.txt ├── fork1 ├── fork1.c ├── fork2 ├── fork2.c ├── system1 ├── system1.c ├── system2 ├── system2.c ├── upper ├── upper.c ├── useupper ├── useupper.c ├── wait └── wait.c ├── Chapter12 ├── thread1 ├── thread1.c ├── thread2 ├── thread2.c ├── thread3 ├── thread3.c ├── thread4 ├── thread4.c ├── thread5 ├── thread5.c ├── thread6 ├── thread6.c ├── thread7 ├── thread7.c ├── thread8 ├── thread8.c ├── thread8a └── thread8a.c ├── Chapter13 ├── client ├── client.c ├── client.h ├── fifo1 ├── fifo1.c ├── fifo2 ├── fifo2.c ├── fifo3 ├── fifo3.c ├── fifo4 ├── fifo4.c ├── pipe1 ├── pipe1.c ├── pipe2 ├── pipe2.c ├── pipe3 ├── pipe3.c ├── pipe4 ├── pipe4.c ├── pipe5 ├── pipe5.c ├── popen1 ├── popen1.c ├── popen2 ├── popen2.c ├── popen3 ├── popen3.c ├── popen4 ├── popen4.c ├── server └── server.c ├── Chapter14 ├── msg1 ├── msg1.c ├── msg2 ├── msg2.c ├── sem1 ├── sem1.c ├── semun.h ├── shm1 ├── shm1.c ├── shm2 ├── shm2.c └── shm_com.h ├── Chapter15 ├── client1 ├── client1.c ├── client2 ├── client2.c ├── client3 ├── client3.c ├── getdate ├── getdate.c ├── getname ├── getname.c ├── select ├── select.c ├── server1 ├── server1.c ├── server2 ├── server2.c ├── server3 ├── server3.c ├── server4 ├── server4.c ├── server5 └── server5.c └── README.md /Chapter02/.while_control.sh.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter02/.while_control.sh.swp -------------------------------------------------------------------------------- /Chapter02/1_tmp: -------------------------------------------------------------------------------- 1 | 123` 2 | -------------------------------------------------------------------------------- /Chapter02/2_tmp: -------------------------------------------------------------------------------- 1 | 456 2 | 3 | -------------------------------------------------------------------------------- /Chapter02/AND_list.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # touch命令判断文件是否存在,若不存在则创建之 4 | touch file_one 5 | 6 | rm -f file_two 7 | 8 | if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there" 9 | then 10 | echo "in if" 11 | else 12 | echo "in else" 13 | fi 14 | 15 | exit 0 16 | -------------------------------------------------------------------------------- /Chapter02/CD_program/title.cdb: -------------------------------------------------------------------------------- 1 | CD123,Cool sax,Jazz,Bix 2 | CD234,Classic violin,Classical,Bach 3 | CD345,Hits99,Popular,Various 4 | CD000, test, Modern, Shang 5 | CD345, FUCK, ok, chao 6 | -------------------------------------------------------------------------------- /Chapter02/CD_program/tracks.cdb: -------------------------------------------------------------------------------- 1 | CD234,1,Sonata in D minor 2 | CD345,1,Dizzy 3 | CD000, 1, 想你的365天 4 | CD000, 2, 最后一页 5 | CD345, 1, boring 6 | CD123, 1, another jazz 7 | CD123, 2, other jazz 8 | -------------------------------------------------------------------------------- /Chapter02/OR_list.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -f file_one 4 | 5 | if [ -f file_one ] || echo "hello" || echo " there" 6 | then 7 | echo "in if" 8 | else 9 | echo "in else" 10 | fi 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /Chapter02/\: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | trap 'rm -f /tmp/my_tmp_file_$$' INT 4 | echo "creating file /tmp/my_tmp_file_$$" 5 | date > /tmp/my_tmp_file_$$ 6 | 7 | echo "press interrupt (CTRL-C) to interrupt the script……" 8 | while [ -f /tmp/my_tmp_file_$$ ] 9 | do 10 | echo "File exists" 11 | sleep 1 12 | done 13 | 14 | echo "The file no longer exists" 15 | 16 | trap INT 17 | 18 | echo "creating file /tmp/my_tmp_file_$$" 19 | 20 | date > /tmp/my_tmp_file_$$ 21 | 22 | echo "press interrupt (CTRL-C) to interrupt the script……" 23 | 24 | while [ -f /tmp/my_tmp_file_$$ ] 25 | do 26 | echo "File exists" 27 | sleep 1 28 | done 29 | 30 | echo "We never get here" 31 | 32 | exit 0 33 | -------------------------------------------------------------------------------- /Chapter02/_1.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /Chapter02/a_simple_function.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | foo() 4 | { 5 | echo "Function foo is executing" 6 | } 7 | 8 | echo "script starting" 9 | 10 | foo 11 | 12 | echo "script ended" 13 | 14 | exit 0 15 | -------------------------------------------------------------------------------- /Chapter02/a_text_file: -------------------------------------------------------------------------------- 1 | This is line 1 2 | This is line 2 3 | Thwas is line 4 4 | -------------------------------------------------------------------------------- /Chapter02/bill.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void bill(char *arg) 4 | { 5 | printf("bill: we passed %s\n",arg); 6 | } 7 | -------------------------------------------------------------------------------- /Chapter02/bill.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter02/bill.o -------------------------------------------------------------------------------- /Chapter02/break_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -rf fred* 4 | 5 | echo > fred1 6 | echo > fred2 7 | 8 | mkdir fred3 9 | 10 | echo > fred4 11 | 12 | for file in fred* 13 | do 14 | if [ -d "$file" ] 15 | then 16 | break 17 | fi 18 | done 19 | 20 | echo "first directory starting fred was $file" 21 | 22 | rm -rf fred* 23 | 24 | exit 0 25 | -------------------------------------------------------------------------------- /Chapter02/case_control.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "Is it morning? Please answer yes or no" 4 | 5 | read timeofday 6 | 7 | case "$timeofday" in 8 | yes ) echo "Good Morning";; 9 | no ) echo "Good Afternoon";; 10 | y ) echo "Good Morning";; 11 | n ) echo "Good Afternoon";; 12 | * ) echo "Sorry, answer not recognized" 13 | esac 14 | 15 | exit 0 16 | 17 | -------------------------------------------------------------------------------- /Chapter02/case_control_2.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "Is it moringing? Please answer yes or no" 4 | 5 | read timeofday 6 | 7 | case "$timeofday" in 8 | yes | y | Yes | YES ) echo "Good Morning";; 9 | no | n | No | NO ) echo "Good Afternoon";; 10 | * ) echo "Sorry, answer not recognized";; 11 | esac 12 | 13 | exit 0 14 | -------------------------------------------------------------------------------- /Chapter02/case_control_3.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "Is it morning? Please answer yes or no" 4 | 5 | read timeofday 6 | 7 | case "$timeofday" in 8 | yes | y | Yes | YES ) 9 | echo "Good Morning" 10 | echo "Up bright and early this morning" 11 | ;; 12 | [nN]* ) 13 | echo "Good Afternoon" 14 | ;; 15 | * ) 16 | echo "Sorry, answer not recognized" 17 | echo "Please answer yes or no" 18 | exit 1 19 | ;; 20 | esac 21 | 22 | exit 0 23 | -------------------------------------------------------------------------------- /Chapter02/colon_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -f fred 4 | 5 | if [ -f fred ] 6 | then 7 | : 8 | else 9 | echo "file fred is not exist" 10 | fi 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /Chapter02/command_executive.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "The current directory is $(pwd)" 4 | 5 | echo "The current uses are $(who)" 6 | 7 | exit 0 8 | -------------------------------------------------------------------------------- /Chapter02/continue_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -rf fred* 4 | 5 | echo > fred1 6 | echo > fred2 7 | mkdir fred3 8 | 9 | echo > fred4 10 | 11 | for file in fred* 12 | do 13 | if [ -d "$file" ] 14 | then 15 | echo "skipping directory $file" 16 | continue 17 | fi 18 | echo "file is $file" 19 | done 20 | 21 | rm -rf fred* 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /Chapter02/elif_condition.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "Is it morning? Please answer yes or no" 4 | 5 | read timeofday 6 | 7 | # 变量的取值需要加上双引号,以防变量是空字符串或者其中存在空格 8 | if [ "$timeofday" = "yes" ] 9 | then 10 | echo "Good morning" 11 | elif [ $timeofday = "no" ] 12 | then 13 | echo "Good afternoon" 14 | else 15 | echo "Sorry, $timeofday not recognized. Enter yes or no" 16 | exit 1 17 | fi 18 | 19 | exit 0 20 | -------------------------------------------------------------------------------- /Chapter02/exit_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | if [ -f .profile ] 4 | then 5 | exit 0 6 | fi 7 | 8 | exit 1 9 | -------------------------------------------------------------------------------- /Chapter02/export1_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "$foo" 4 | echo "$bar" 5 | -------------------------------------------------------------------------------- /Chapter02/export2_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | foo="The first meta-synatactic variable" 4 | 5 | export bar="The second meta-syntactic variable" 6 | 7 | ./export1_command.sh 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /Chapter02/first: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # This is the first shell script in the book Linux程序设计 4 | # This script search for the string "POSIX" in all of files 5 | # and it will print the file's content which have string "POSIX" 6 | 7 | for file in * 8 | do 9 | if grep -l POSIX $file 10 | then 11 | echo $file 12 | fi 13 | done 14 | 15 | # 退出状态码是很重要的,用来判断程序是否正常执行 16 | exit 0 17 | -------------------------------------------------------------------------------- /Chapter02/for_control.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | for foo in bar fud 43 3 | do 4 | echo "$foo" 5 | done 6 | 7 | exit 0 8 | -------------------------------------------------------------------------------- /Chapter02/for_control_*.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | for file in $(ls f*.sh) 4 | do 5 | echo "$file" 6 | done 7 | 8 | exit 0 9 | -------------------------------------------------------------------------------- /Chapter02/giftojpeg.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # unfortunately, my system doesn't have program named cjpeg 4 | # 为每个GIF文件创建一个对应的JPEG文件,通过cjpeg脚本和参数扩展来实现 5 | for image in *.gif 6 | do 7 | cjpeg $image > ${image%%gif}jpg # 参数扩展:从尾部开始删除与gif匹配最长的部分,即将文件名中和gif有关的部分删除改成jpg 8 | done 9 | 10 | exit 0 11 | -------------------------------------------------------------------------------- /Chapter02/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter02/hello -------------------------------------------------------------------------------- /Chapter02/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | printf("Hello World\n"); 8 | exit(0); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter02/here_document_with_ed.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ed a_text_file < 2 | 3 | #include "lib.h" //使用当前目录下的lib头文件 4 | 5 | int main() 6 | { 7 | bill("Hello World\n"); 8 | exit(0); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter02/program.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter02/program.o -------------------------------------------------------------------------------- /Chapter02/questions.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Ask some questions and collect the answer 4 | 5 | # Display a welcome box 6 | dialog --title "Questionnaire" --msgbox "Welcome to my simple survey" 9 18 7 | 8 | # Display a Confirm box, and let user to choose whether he'd like to play 9 | dialog --title "Confirm" --yesno "Are you willing to take part?" 9 18 10 | 11 | # Check the quit status of the last command, if it's not zero, then it mens the user doesn't want to play, so just clear up, and quit 12 | if [ $? != 0 ] 13 | then 14 | dialog --infobox "Thank you anyway" 5 20 15 | sleep 2 16 | dialog --clear 17 | exit 0 18 | fi 19 | 20 | # Display a inputbox, and let user enter his name, then redirect it's input to a tmp file 21 | dialog --title "Questionnaire" --inputbox "Please enter your name" 9 30 2> _1.txt 22 | 23 | # Get user's name from tmp file, and give it to a variable named Q_NAME 24 | Q_NAME=$(cat _1.txt) 25 | 26 | # Display a menu, and let user choose his favoritue music' type 27 | dialog --menu "$Q_NAME, what music do you like best?" 15 30 4 1 "Classical" 2 "Jazz" 3 "Country" 4 "Other" 2>_1.txt 28 | 29 | # just like above, get user's answer from tmp file 30 | Q_MUSIC=$(cat _1.txt) 31 | 32 | 33 | # Check user's choice of music, and test whether it is Classical 34 | if [ "$Q_MUSIC" = "1" ] 35 | then 36 | dialog --title "like Classical" --msgbox "Good choice!" 12 25 37 | else 38 | dialog --title "Doesn't like Classical" --msgbox "Shame" 12 25 39 | fi 40 | 41 | 42 | # Finally, clear up and exit 43 | sleep 2 44 | dialog --clear 45 | exit 0 46 | -------------------------------------------------------------------------------- /Chapter02/return_from_function.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | yes_or_no() 4 | { 5 | echo "Is your name $* ?" 6 | while true 7 | do 8 | echo -n "Enter yes or no: " 9 | read x 10 | case "$x" in 11 | y | yes ) return 0;; 12 | n | no ) return 1;; 13 | * ) echo "Answer yes or no" 14 | esac 15 | done 16 | } 17 | 18 | echo "Original parameters are $*" 19 | 20 | if yes_or_no "$1" 21 | then 22 | echo "Hi $1, nice meet" 23 | else 24 | echo "Never mind" 25 | fi 26 | 27 | exit 0 28 | -------------------------------------------------------------------------------- /Chapter02/set_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | set $(date) 4 | 5 | echo "The month is "$2"" 6 | 7 | exit 0 8 | -------------------------------------------------------------------------------- /Chapter02/shift_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | while [ "$1" != "" ] 4 | do 5 | echo "$1" 6 | shift 7 | done 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /Chapter02/signal_process.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | trap 'rm -f /tmp/my_tmp_file_$$' INT 4 | echo "creating file /tmp/my_tmp_file_$$" 5 | date > /tmp/my_tmp_file_$$ 6 | 7 | echo "press interrupt (CTRL-C) to interrupt the script……" 8 | while [ -f /tmp/my_tmp_file_$$ ] 9 | do 10 | echo "File exists" 11 | sleep 1 12 | done 13 | 14 | echo "The file no longer exists" 15 | 16 | trap INT 17 | 18 | echo "creating file /tmp/my_tmp_file_$$" 19 | 20 | date > /tmp/my_tmp_file_$$ 21 | 22 | echo "press interrupt (CTRL-C) to interrupt the script……" 23 | 24 | while [ -f /tmp/my_tmp_file_$$ ] 25 | do 26 | echo "File exists" 27 | sleep 1 28 | done 29 | 30 | echo "We never get here" 31 | 32 | exit 0 33 | -------------------------------------------------------------------------------- /Chapter02/test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter02/test.gif -------------------------------------------------------------------------------- /Chapter02/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter02/test.jpg -------------------------------------------------------------------------------- /Chapter02/test_command: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | if [ -f /bin/bash ] 4 | then 5 | echo "file /bin/bash exists." 6 | fi 7 | 8 | if [ -d /bin/bash ] 9 | then 10 | echo "/bin/bash is a directory" 11 | else 12 | echo "/bin/bash is not a directory" 13 | fi 14 | -------------------------------------------------------------------------------- /Chapter02/try_var: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | salutation="Hello" 4 | 5 | echo $salutation 6 | echo "The program $0 is now running" 7 | echo "The second parameter was $2" 8 | echo "The first parameter was $1" 9 | echo "the parameter list was $*" 10 | echo "The user's home directory is $HOME" 11 | 12 | echo "Please enter a new greeting" 13 | read salutation 14 | 15 | echo $salutation 16 | echo "The script is now complete" 17 | exit 0 18 | -------------------------------------------------------------------------------- /Chapter02/unset_command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | foo="Hello World" 4 | 5 | echo "$foo" 6 | 7 | unset foo 8 | 9 | echo "$foo" 10 | 11 | exit 0 12 | -------------------------------------------------------------------------------- /Chapter02/until_control.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | until who | grep "$1" > /dev/null 4 | do 5 | sleep 60 6 | done 7 | 8 | # now ring the bell and announce the expected user. 9 | 10 | echo '\a' 11 | 12 | echo "**** $1 has just logged in ****" 13 | 14 | exit 0 15 | -------------------------------------------------------------------------------- /Chapter02/variable: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | myvar="Hi there" 4 | 5 | echo $myvar 6 | echo "$myvar" 7 | echo '$myvar' 8 | echo \$myvar 9 | 10 | echo Enter some text 11 | read myvar 12 | 13 | echo '$myvar' now equals $myvar 14 | exit 0 15 | -------------------------------------------------------------------------------- /Chapter02/while_control.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "Enter password" 4 | read trythis 5 | 6 | while [ "$trythis" != "secret" ] 7 | do 8 | echo "sorry, try again" 9 | read trythis 10 | done 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /Chapter02/words2.txt: -------------------------------------------------------------------------------- 1 | Is this a dagger which I see before me, 2 | The handle toward my hand? Come, let me clutch thee. 3 | I have thee not, and yet I see thee still. 4 | Art thou not, fatal vision, sensible 5 | To feeling as to sight? or art thou but 6 | A dagger of the mind, a false creation, 7 | Proceeding from the heat-oppressed brain? 8 | I see thee yet, in form as palpable 9 | As this which now I draw. 10 | Thou marshall'st me the way that I was going; 11 | And such an instrument I was to use. 12 | Mine eyes are made the fools o' the other senses, 13 | Or else worth all the rest; I see thee still, 14 | And on thy blade and dudgeon gouts of blood, 15 | Which was not so before. There's no such thing: 16 | It is the bloody business which informs 17 | Thus to mine eyes. Now o'er the one halfworld 18 | Nature seems dead, and wicked dreams abuse 19 | The curtain'd sleep; witchcraft celebrates 20 | Pale Hecate's offerings, and wither'd murder, 21 | Alarum'd by his sentinel, the wolf, 22 | Whose howl's his watch, thus with his stealthy pace. 23 | With Tarquin's ravishing strides, towards his design 24 | Moves like a ghost. Thou sure and firm-set earth, 25 | Hear not my steps, which way they walk, for fear 26 | Thy very stones prate of my whereabout, 27 | And take the present horror from the time, 28 | Which now suits with it. Whiles I threat, he lives: 29 | Words to the heat of deeds too cold breath gives. 30 | 31 | -------------------------------------------------------------------------------- /Chapter03/copy_block: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter03/copy_block -------------------------------------------------------------------------------- /Chapter03/copy_block.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | char block[1024]; 9 | int in, out; 10 | int nread; 11 | 12 | in = open("file.in",O_RDONLY); 13 | out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); 14 | 15 | while ((nread = read(in, block, sizeof(block))) > 0) 16 | write(out, block, nread); 17 | 18 | exit (0); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter03/copy_stdio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter03/copy_stdio -------------------------------------------------------------------------------- /Chapter03/copy_stdio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | int c; 7 | FILE *in, *out; 8 | in = fopen("file.in","r"); 9 | out = fopen("file.out","w"); 10 | 11 | while ((c = fgetc(in)) != EOF) 12 | { 13 | fputc(c,out); 14 | } 15 | exit (0); 16 | } 17 | -------------------------------------------------------------------------------- /Chapter03/copy_system: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter03/copy_system -------------------------------------------------------------------------------- /Chapter03/copy_system.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //一个使用open、read和write等系统调用完成的底层复制程序,用来逐个字符的把一个文件复制到另一个文件 7 | 8 | int main() 9 | { 10 | char c; 11 | int in, out; 12 | in = open("file.in", O_RDONLY); 13 | out = open("file.out", O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); 14 | while(read(in,&c,1) == 1) 15 | { 16 | write(out,&c,1); 17 | } 18 | exit (0); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter03/draft1.txt: -------------------------------------------------------------------------------- 1 | Files 2 | In this chapter we will be looking at files and directories and how to manipulate them. We will learn how to create files,open them, read, write and close them. We'll also learn how programs can manipulate directories, to create, scan and delete them, for example. After the last chapter's diversion into shells, we now start programming in C. 3 | Before proceeding to the way UNIX handles file I/O, we'll review the concepts associated with files, directories and devices. To manipulate files and directories, we need to make system calls (the UNIX parallel of the Windows API), but there also exists a whole range of library functions, the standard I/O library (stdio), to make file handling more efficient. 4 | -------------------------------------------------------------------------------- /Chapter03/mmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter03/mmap -------------------------------------------------------------------------------- /Chapter03/mmap.c: -------------------------------------------------------------------------------- 1 | /* 利用mmap和数组方式的存取操作来修改一个结构化数据文件 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef struct //定义一个RECORD结构 10 | { 11 | int integer; 12 | char string[24]; 13 | }RECORD; 14 | 15 | #define NRECORDS (100) //创建100个记录 16 | 17 | int main() 18 | { 19 | RECORD record, *mapped; 20 | int i, f; 21 | FILE *fp; 22 | 23 | fp = fopen("records.dat","w+"); //将100个记录写到文件records.dat中 24 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void printdir(char *dir, int depth) 9 | { 10 | DIR *dp; 11 | struct dirent *entry; 12 | struct stat statbuf; 13 | 14 | if ((dp = opendir(dir)) == NULL) 15 | { 16 | fprintf(stderr, "cannot open directory: %s\n", dir); 17 | return; 18 | } 19 | chdir(dir); //调用dir切换到指定目录 20 | while ((entry = readdir(dp)) != NULL) 21 | { 22 | lstat(entry->d_name, &statbuf); 23 | if (S_ISDIR(statbuf.st_mode)) //判断是不是目录,若是目录,则进入if语句 24 | { 25 | /*Found a directory, but ignore . and ..*/ 26 | if (strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0) //检查该数据项是不是.或者.. 27 | { 28 | continue; 29 | } 30 | printf("%*s%s\n",depth,"",entry->d_name); //如果不是.或者..,则输出以depth缩排的目录名 31 | /* 递归遍历 */ 32 | printdir(entry->d_name,depth+4); //对该目录进行递归调用将该目录中的所有子目录和文件的名字都输出,同时缩进加4个空格 33 | } 34 | else 35 | { 36 | printf("%*s%s\n",depth,"",entry->d_name); //如果不是目录,则输出文件的名字 37 | } 38 | } 39 | chdir(".."); //当while循环结束后,即当前目录遍历完后,退回到上一层目录,然后继续目录的遍历 40 | closedir(dp); //调用closedir及时关闭遍历完的目录,确保了打开的目录流数目不超出限制 41 | } 42 | 43 | int main(int argc, char *argv[]) 44 | { 45 | char *topdir = "."; 46 | if (argc >= 2) 47 | { 48 | topdir = argv[1]; 49 | } 50 | printf("Directory scan of %s:\n",topdir); 51 | printdir(topdir,0); 52 | printf("done.\n"); 53 | exit (0); 54 | } 55 | -------------------------------------------------------------------------------- /Chapter03/records.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter03/records.dat -------------------------------------------------------------------------------- /Chapter03/simple_read: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter03/simple_read -------------------------------------------------------------------------------- /Chapter03/simple_read.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Linux系统库函数中read函数的原型: 6 | size_t read(int fildes, void *buf, size_t nbytes); 7 | fildes:某文件的文件描述符 8 | buf:缓冲区 9 | nbytes:要读入的字节数 10 | */ 11 | 12 | int main() 13 | { 14 | char buffer[128]; 15 | int nread; 16 | 17 | nread = read(0,buffer,128); 18 | if (nread == -1) //判断read函数是否返回值为-1,即是否出错 19 | { 20 | write(2,"A read error has occurred\n",26); 21 | } 22 | 23 | if ((write(1,buffer,nread)) != nread) //将读入的数据写入到标准输出 24 | { 25 | write(2,"A write error has occurred\n",26); 26 | } 27 | 28 | exit (0); 29 | } 30 | -------------------------------------------------------------------------------- /Chapter03/simple_write: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter03/simple_write -------------------------------------------------------------------------------- /Chapter03/simple_write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //Linux库函数中write函数的原型: 5 | /* 6 | size_t write(int fildes, const void *buf, size_t nbytes); 7 | fildes:某文件的文件描述符 8 | buf:缓冲区 9 | nbytes:要写入的字节数 10 | */ 11 | 12 | int main() 13 | { 14 | if ((write(1,"Here is some data\n",18))!=18) 15 | { 16 | write(2,"A write error has occurred on file descripter 1\n",46); 17 | } 18 | exit (0); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter04/argopt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/argopt -------------------------------------------------------------------------------- /Chapter04/argopt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | int opt; 8 | 9 | while ((opt = getopt(argc, argv, ":if:lr")) != -1) //opt指向下一个选项字符 10 | { 11 | switch(opt) 12 | { 13 | case 'i': 14 | case 'l': 15 | case 'r': 16 | printf("option: %c\n",opt); 17 | break; 18 | case 'f': 19 | printf("filename: %s\n",optarg); //optarg是一个外部变量,指向选项的关联值 20 | break; 21 | case ':': 22 | printf("option needs a value\n"); 23 | break; 24 | case '?': 25 | printf("unknown option: %c\n",optopt); //optopt存储无法识别的选项 26 | } 27 | } 28 | for(;optind 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | for (int arg=0;arg 2 | #include 3 | #include 4 | 5 | /* 使用ctime或者asctime函数来更友好的显示时间和日期 */ 6 | /* asctime()函数结构struct tm *结构,并返回一个包含时间和日期的字符串; 7 | ctime()函数结构一个纯秒数,并返回一个包含时间和日期的字符串 8 | */ 9 | 10 | int main() 11 | { 12 | time_t timeval; 13 | struct tm *tm_ptr; 14 | (void) time(&timeval); 15 | tm_ptr = gmtime(&timeval); 16 | //printf("The data is: %s",ctime(&timeval)); 17 | printf("The data is: %s\n",asctime(tm_ptr)); 18 | exit (0); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter04/environ: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/environ -------------------------------------------------------------------------------- /Chapter04/environ.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | char *var, *value; 8 | 9 | if (argc == 1 || argc > 3) 10 | { 11 | fprintf(stderr, "usage: environ var [value]\n"); 12 | exit (1); 13 | } 14 | /* 调用getenv从环境中取出变量的值 */ 15 | var = argv[1]; //取得第一个命令行参数 16 | value = getenv(var); //取得该参数的值 17 | if (value) //若值存在,则执行if语句块 18 | { 19 | printf("Variable %s has value %s\n", var, value); 20 | } 21 | else //若该参数(变量)不存在,或者变量存在,但是没有关联的值,则返回null 22 | { 23 | printf("Variable %s has no value\n", var); 24 | } 25 | 26 | /* 检查程序是否还有第二个参数,若有,则构建一个格式为"名字=值"的字符串并调用putenv来设置变量的值 */ 27 | if (argc == 3) //argc==3,说明一共有两个参数 28 | { 29 | char *string; 30 | value = argv[2]; 31 | string = malloc(strlen(var) + strlen(value) + 2); //分配能够存储变量、变量值、及等号的内存空间 32 | if (!string) 33 | { 34 | fprintf(stderr,"out of memory\n"); 35 | exit (1); 36 | } 37 | strcpy(string,var); 38 | strcat(string,"="); 39 | strcat(string,value); 40 | printf("Calling putenv with: %s\n",string); 41 | if (putenv(string) != 0) 42 | { 43 | fprintf(stderr, "putenv failed\n"); 44 | free(string); 45 | exit (1); 46 | } 47 | /* 再次调用getenv来查看变量的新值 */ 48 | value = getenv(var); 49 | if (value) 50 | { 51 | printf("New value of %s is %s\n", var, value); 52 | } 53 | else 54 | { 55 | printf("New value of %s is null??\n", var); 56 | } 57 | } 58 | exit (0); 59 | } 60 | -------------------------------------------------------------------------------- /Chapter04/envtime: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/envtime -------------------------------------------------------------------------------- /Chapter04/envtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int i; 9 | time_t the_time; 10 | 11 | for (i = 1;i <= 10;i++) 12 | { 13 | the_time = time((time_t *)0); //返回自1970.1.1 0点至今的秒数,是一个长整形,存储在time()函数中的参数中。 14 | printf("The time is %ld\n", the_time); 15 | sleep(2); 16 | } 17 | exit (0); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter04/gmtime: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/gmtime -------------------------------------------------------------------------------- /Chapter04/gmtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | struct tm *tm_ptr; //tm结构中包含分开的时、分、秒、日、月、年、星期、年份中的日期、是否使用夏令时等 9 | time_t the_time; 10 | 11 | (void) time(&the_time); 12 | //tm_ptr = gmtime(&the_time); //通过gmtime()函数将纯秒数转换为tm结构 13 | tm_ptr = localtime(&the_time); 14 | /* 如果运行该函数时,在格林尼治标准时间(GMT)之外的时区,或者采用了夏令时,则时间有可能不正确。*/ 15 | /* 若想返回正确的时间,可以使用localtime()函数来查看当地时间,其返回的值已根据当地时区和是否使用夏令时调整 */ 16 | printf("Raw time is %ld\n", the_time); 17 | printf("gmtime gives:\n"); 18 | printf("date: %02d/%02d/%02d\n",tm_ptr->tm_year,tm_ptr->tm_mon+1,tm_ptr->tm_mday); 19 | printf("time: %02d:%02d:%02d\n",tm_ptr->tm_hour,tm_ptr->tm_min,tm_ptr->tm_sec); 20 | exit (0); 21 | } 22 | -------------------------------------------------------------------------------- /Chapter04/hostget: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/hostget -------------------------------------------------------------------------------- /Chapter04/hostget.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | char computer[256]; 9 | struct utsname uts; 10 | /* gethostname()函数把机器的网络名写入computer字符串,该字符串至少有255个字符; 11 | uname()函数把主机信息写入uts指向的结构体中 12 | */ 13 | if (gethostname(computer, 255) != 0 || uname(&uts) < 0) 14 | { 15 | fprintf(stderr, "Could not get host information\n"); 16 | exit (1); 17 | } 18 | 19 | printf("Computer host name is %s\n", computer); //输出主机名 20 | printf("System is %s on %s hardware\n", uts.sysname, uts.machine); //输出操作系统名、硬件类型 21 | printf("Nodename is %s\n", uts.nodename); //输出主机名 22 | printf("Version is %s, %s\n", uts.release, uts.version); //输出系统发行级别、系统版本号 23 | exit (0); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter04/limits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/limits -------------------------------------------------------------------------------- /Chapter04/limits.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void work() 10 | { 11 | FILE *f; 12 | int i; 13 | double x = 4.5; 14 | 15 | f = tmpfile(); 16 | for (i = 0;i < 10000;i++) 17 | { 18 | fprintf(f,"Do some output\n"); 19 | if (ferror(f)) 20 | { 21 | fprintf(stderr, "Error writing to temporary file\n"); 22 | exit (1); 23 | } 24 | } 25 | for (i = 0;i < 1000000;i++) 26 | { 27 | x = log(x*x + 3.21); //注意:使用log函数时,若使用gcc编译,则需要加上-lm 28 | } 29 | } 30 | 31 | int main() 32 | { 33 | struct rusage r_usage; 34 | struct rlimit r_limit; 35 | int priority; 36 | /* 调用work函数,来产生CPU负载,再调用getrusage函数来发现它消耗的CPU时间,并将其显示 */ 37 | work(); 38 | getrusage(RUSAGE_SELF,&r_usage); 39 | 40 | printf("CPU usage: User = %ld.%06ld, System = %ld.%06ld\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec, r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec); //分别显示用户时间的秒和微秒,系统时间的秒和微秒 41 | 42 | /* 分别调用getpriority和getrlimit来发现它的当前优先级和文件大小限制 */ 43 | priority = getpriority(PRIO_PROCESS,getpid()); 44 | printf("Current priority = %d\n", priority); 45 | 46 | getrlimit(RLIMIT_FSIZE,&r_limit); 47 | printf("Current FSIZE limit: soft = %ld, hard = %ld\n", r_limit.rlim_cur, r_limit.rlim_max); 48 | 49 | /* 最后,调用setrlimit设置文件大小限制并再次调用work */ 50 | r_limit.rlim_cur = 2048; 51 | r_limit.rlim_max = 4096; 52 | printf("Setting a 2K file size limit\n"); 53 | setrlimit(RLIMIT_FSIZE, &r_limit); 54 | 55 | work(); 56 | exit (0); 57 | } 58 | -------------------------------------------------------------------------------- /Chapter04/logmask: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/logmask -------------------------------------------------------------------------------- /Chapter04/logmask.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* void openlog(const char *ident, int logopt, int facility); 7 | 调用opoenlog函数来改变日志信息的表示方式。 8 | ident:该字符串添加在日志信息的前面,可以通过该字符串来指明是哪个程序创建了这条信息 9 | logopt:对后续syslog()函数调用的行为进行配置 10 | facility:该参数记录一个将被用于后续syslog调用的默认设施值 11 | */ 12 | 13 | /* int setlogmask(int maskpri); 14 | 调用setlogmask函数来设置一个日志掩码,并通过它来控制日志信息的优先级。 15 | maskpri有两种方式: 16 | ① LOG_MASK(priority)为日志信息创建一个掩码,它的作用是创建一个只包含一个优先级的掩码 17 | ② LOG_UPTO(priority)来创建一个指定优先级之上的所有优先级(包括指定优先级)构成的掩码 18 | */ 19 | int main() 20 | { 21 | int logmask; 22 | 23 | openlog("logmask", LOG_PID|LOG_CONS,LOG_USER); 24 | syslog(LOG_INFO,"informative message,pid = %d", getpid()); 25 | syslog(LOG_DEBUG, "debug message, should appear"); 26 | logmask = setlogmask(LOG_UPTO(LOG_NOTICE)); 27 | syslog(LOG_DEBUG, "debug message, should not appear"); //该语句的优先级为DEBUG,低于上一句设定的NOTICE,所以不会显示:w 28 | exit (0); 29 | } 30 | -------------------------------------------------------------------------------- /Chapter04/longopt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/longopt -------------------------------------------------------------------------------- /Chapter04/longopt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define _GNU_SOURCE //与头文件getopt.h一同包含进来,启用getopt_long功能 6 | #include 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | int opt; 11 | struct option longopts[]= //结构数组,描述每个长选项并告诉getopt_long()怎么处理它们 12 | { 13 | {"initialize",0,NULL,'i'}, //依次为长选项的名字、该选项是否带参数、NULL表示找到该选项时,getopt_long返回第四个成员的值、该选项要返回的值 14 | {"file",1,NULL,'f'}, 15 | {"list",0,NULL,'l'}, 16 | {"restart",0,NULL,'r'}, 17 | {0,0,0,0} //该结构体必须以此结尾 18 | }; 19 | 20 | while ((opt = getopt_long(argc, argv, ":if:lr", longopts, NULL)) != -1) //opt指向下一个选项字符 21 | { 22 | switch(opt) 23 | { 24 | case 'i': 25 | case 'l': 26 | case 'r': 27 | printf("option: %c\n",opt); 28 | break; 29 | case 'f': 30 | printf("filename: %s\n",optarg); //optarg是一个外部变量,指向选项的关联值 31 | break; 32 | case ':': 33 | printf("option needs a value\n"); 34 | break; 35 | case '?': 36 | printf("unknown option: %c\n",optopt); //optopt存储无法识别的选项 37 | } 38 | } 39 | for(;optind 2 | #include 3 | 4 | extern char **environ; 5 | 6 | int main() 7 | { 8 | char **env = environ; 9 | while (*env) 10 | { 11 | printf("%s\n",*env); 12 | env++; 13 | } 14 | exit (0); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter04/strftime: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/strftime -------------------------------------------------------------------------------- /Chapter04/strftime.c: -------------------------------------------------------------------------------- 1 | # define _XOPEN_SOURCE //GNU库在默认情况下并未声明strptime函数,需要明确请求使用X/Open的标准功能,需要在time.h前添加该行 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | struct tm *tm_ptr, timestruct; 10 | time_t the_time; 11 | char buf[256]; 12 | char *result; 13 | 14 | (void) time(&the_time); 15 | tm_ptr = localtime(&the_time); 16 | strftime(buf,256,"%A %d %B, %I:%S %p", tm_ptr); 17 | 18 | printf("strftime gives: %s\n",buf); 19 | 20 | /* 为了演示strptime的用法,构建一个包含日期和时间的字符串,然后调用strptime将原始时间和日期值提取并打印出来 */ 21 | strcpy(buf,"Thu 26 July 2007, 17:53 will do fine"); 22 | 23 | printf("calling strptime with :%s\n",buf); 24 | tm_ptr = ×truct; //将tm_prt重新赋值,相当于清空 25 | 26 | result = strptime(buf,"%a %d %b %Y, %R",tm_ptr); //从buf中提取出原始时间和日期,存储在struct tm *结构中 27 | printf("strptime consumed up to: %s\n", result); //strptime函数返回一个指针,指向转换过程处理的最后一个字符后面的字符 28 | 29 | printf("strptime gives:\n"); 30 | printf("date: %02d/%02d/%02d\n", tm_ptr->tm_year%100, tm_ptr->tm_mon+1, tm_ptr->tm_mday); 31 | printf("time: %02d:%02d\n",tm_ptr->tm_hour,tm_ptr->tm_min); 32 | exit (0); 33 | } 34 | -------------------------------------------------------------------------------- /Chapter04/syslog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/syslog -------------------------------------------------------------------------------- /Chapter04/syslog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | FILE *f; 8 | 9 | f = fopen("not here", "r"); 10 | if (!f) 11 | { 12 | syslog(LOG_ERR|LOG_USER,"oops - %m\n"); 13 | } 14 | exit (0); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter04/tmpnam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/tmpnam -------------------------------------------------------------------------------- /Chapter04/tmpnam.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | char tmpname[L_tmpnam]; 7 | char *filename; 8 | FILE *tmpfp; 9 | 10 | filename = tmpnam(tmpname); //tmpnam()函数为临时文件生成一个唯一的文件名,若tmpname不为空,则文件名也会写入tmpname,即tmpname中的内容与filename中的内容相同。 11 | 12 | printf("Temporary file name is: %s\n", filename); 13 | tmpfp = tmpfile(); //tmpfile()函数是一种更安全的做法,它创建并打开一个临时文件,且具有唯一的文件名,避免了另一个程序用同样的名字打开临时文件的风险。 14 | if (tmpfp) 15 | { 16 | printf("Opened a temporary file OK\n"); 17 | } 18 | else 19 | { 20 | perror("tmpfile"); 21 | } 22 | exit (0); 23 | } 24 | -------------------------------------------------------------------------------- /Chapter04/user: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter04/user -------------------------------------------------------------------------------- /Chapter04/user.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | uid_t uid; 10 | gid_t gid; 11 | 12 | struct passwd *pw; 13 | uid = getuid(); //获取当前程序关联的用户ID,即启动程序的用户的ID 14 | gid = getgid(); //获取启动程序的用户所在组的ID 15 | 16 | printf("User is %s\n",getlogin()); //getlogin()函数返回当前用户关联的登录名 17 | printf("User IDs:uid=%d, gid=%d\n", uid, gid); 18 | 19 | pw = getpwuid(uid); //用过uid参数来获得用户信息 20 | printf("UID passwd entry:\nname=%s, uid=%d, gid=%d, home=%s, shell=%s\n",pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell); 21 | 22 | pw = getpwnam("root"); //以用户登录名来查找用户信息 23 | printf("root passed entry:\n"); 24 | printf("name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell); 25 | exit (0); 26 | } 27 | -------------------------------------------------------------------------------- /Chapter05/badterm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/badterm -------------------------------------------------------------------------------- /Chapter05/badterm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | setupterm("unlisted", fileno(stdout), (int *)0); 9 | printf("Done.\n"); 10 | exit (0); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter05/file: -------------------------------------------------------------------------------- 1 | You have chosen: a 2 | You have chosen: d 3 | You have chosen: q 4 | -------------------------------------------------------------------------------- /Chapter05/file.error: -------------------------------------------------------------------------------- 1 | You are not a terminal! 2 | -------------------------------------------------------------------------------- /Chapter05/kbhit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/kbhit -------------------------------------------------------------------------------- /Chapter05/kbhit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static struct termios initial_settings, new_settings; 9 | static int peek_character = -1; 10 | 11 | void init_keyboard(); 12 | void close_keyboard(); 13 | int kbhit(); 14 | int readch(); 15 | 16 | int main() 17 | { 18 | /* 调用init_keyboard函数来配置终端,每隔1秒循环调用一次kbhit函数 */ 19 | int ch = 0; 20 | init_keyboard(); 21 | while (ch != 'q') 22 | { 23 | printf("looping\n"); 24 | sleep(1); 25 | if (kbhit()) 26 | { 27 | ch = readch(); 28 | printf("you hit %c\n", ch); 29 | } 30 | } 31 | close_keyboard(); 32 | exit (0); 33 | } 34 | 35 | /* init_keyboard函数在程序的开始对终端进行配置 */ 36 | void init_keyboard() 37 | { 38 | tcgetattr(0, &initial_settings); 39 | new_settings = initial_settings; 40 | new_settings.c_lflag &= ~ICANON; 41 | new_settings.c_lflag &= ~ECHO; 42 | new_settings.c_lflag &= ~ISIG; 43 | new_settings.c_cc[VMIN] = 1; 44 | new_settings.c_cc[VTIME] = 0; 45 | tcsetattr(0, TCSANOW, &new_settings); 46 | } 47 | 48 | 49 | /* close_keyboard函数在程序的结束对终端配置还原 */ 50 | void close_keyboard() 51 | { 52 | tcsetattr(0, TCSANOW, &initial_settings); 53 | } 54 | 55 | /* kbhit函数检测是否有按键按下 */ 56 | int kbhit() 57 | { 58 | char ch; 59 | int nread; 60 | 61 | if (peek_character != -1) 62 | { 63 | return 1; 64 | } 65 | new_settings.c_cc[VMIN] = 0; 66 | tcsetattr(0, TCSANOW, &new_settings); 67 | nread = read(0, &ch, 1); 68 | new_settings.c_cc[VMIN] = 1; 69 | tcsetattr(0, TCSANOW, &new_settings); 70 | 71 | if (nread == 1) 72 | { 73 | peek_character = ch; 74 | return 1; 75 | } 76 | return 0; 77 | } 78 | 79 | /* readch函数读取按下的按键 */ 80 | int readch() 81 | { 82 | char ch; 83 | 84 | if (peek_character != -1) 85 | { 86 | ch = peek_character; 87 | peek_character = -1; 88 | return ch; 89 | } 90 | read(0, &ch, 1); 91 | return ch; 92 | } 93 | -------------------------------------------------------------------------------- /Chapter05/menu1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/menu1 -------------------------------------------------------------------------------- /Chapter05/menu1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //定义菜单字符串数组 5 | char *menu[] = {"a - add new record","d - delete record","q - quit",NULL,}; 6 | 7 | int getchoice(char *greet, char *choices[]); 8 | 9 | int main() 10 | { 11 | int choice = 0; 12 | 13 | do 14 | { 15 | choice = getchoice("Please select an action", menu); //显示菜单信息,并等待用户输入菜单选项首字母 16 | printf("You have chosen: %c\n", choice); 17 | //getchar(); //使用getchar()函数来吃掉(忽略掉)回车符。Notice:当输入错误字符时,还是有问题,应该在子函数中进行修改 18 | } while(choice != 'q'); //直到用户输入q想要退出,否则一直循环 19 | exit (0); 20 | } 21 | 22 | /* 显示菜单,及读取用户输入 */ 23 | int getchoice(char *greet, char *choices[]) 24 | { 25 | int chosen = 0; 26 | int selected; 27 | char **option; 28 | 29 | do //不断循环直到用户输入正确的选项 30 | { 31 | printf("Choice: %s\n", greet); 32 | option = choices; 33 | while (*option) //通过一个while循环,将字符串数组中的所有内容显示出来 34 | { 35 | printf("%s\n", *option); 36 | option++; 37 | } 38 | 39 | do 40 | { 41 | selected = getchar(); //从终端读取用户输入 42 | } while (selected == '\n'); 43 | 44 | option = choices; 45 | while (*option) 46 | { 47 | if (selected == *option[0]) //判断用户输入是否符合菜单中某个选项 48 | { 49 | chosen = 1; 50 | break; 51 | } 52 | option++; 53 | } 54 | if (!chosen) 55 | { 56 | printf("Incorrect choice, select again\n"); 57 | } 58 | } while(!chosen); 59 | return selected; 60 | } 61 | -------------------------------------------------------------------------------- /Chapter05/menu2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/menu2 -------------------------------------------------------------------------------- /Chapter05/menu2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //定义菜单字符串数组 6 | char *menu[] = {"a - add new record","d - delete record","q - quit",NULL,}; 7 | 8 | int getchoice(char *greet, char *choices[]); 9 | 10 | int main() 11 | { 12 | int choice = 0; 13 | 14 | if (!isatty(fileno(stdout))) //fileno将文件流转换成文件描述符,isatty判断该描述符是否连接到一个终端 15 | { 16 | fprintf(stderr, "You are not a terminal!\n"); 17 | exit (1); 18 | } 19 | 20 | do 21 | { 22 | choice = getchoice("Please select an action", menu); //显示菜单信息,并等待用户输入菜单选项首字母 23 | printf("You have chosen: %c\n", choice); 24 | } while(choice != 'q'); //直到用户输入q想要退出,否则一直循环 25 | exit (0); 26 | } 27 | 28 | /* 显示菜单,及读取用户输入 */ 29 | int getchoice(char *greet, char *choices[]) 30 | { 31 | int chosen = 0; 32 | int selected; 33 | char **option; 34 | 35 | do //不断循环直到用户输入正确的选项 36 | { 37 | printf("Choice: %s\n", greet); 38 | option = choices; 39 | while (*option) //通过一个while循环,将字符串数组中的所有内容显示出来 40 | { 41 | printf("%s\n", *option); 42 | option++; 43 | } 44 | 45 | do 46 | { 47 | selected = getchar(); //从终端读取用户输入 48 | } while (selected == '\n'); 49 | 50 | option = choices; 51 | while (*option) 52 | { 53 | if (selected == *option[0]) //判断用户输入是否符合菜单中某个选项 54 | { 55 | chosen = 1; 56 | break; 57 | } 58 | option++; 59 | } 60 | if (!chosen) 61 | { 62 | printf("Incorrect choice, select again\n"); 63 | } 64 | } while(!chosen); 65 | return selected; 66 | } 67 | -------------------------------------------------------------------------------- /Chapter05/menu3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/menu3 -------------------------------------------------------------------------------- /Chapter05/menu3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 该程序将与用户交互的部分和其他的输入输出分开,只将输入和输出进行重定向,需要将与用户交互的部分与stdout、stderr分离开 */ 6 | 7 | //定义菜单字符串数组 8 | char *menu[] = {"a - add new record","d - delete record","q - quit",NULL,}; 9 | 10 | int getchoice(char *greet, char *choices[], FILE *in, FILE *out); 11 | 12 | int main() 13 | { 14 | int choice = 0; 15 | FILE *input; 16 | FILE *output; 17 | 18 | if (!isatty(fileno(stdout))) //fileno将文件流转换成文件描述符,isatty判断该描述符是否连接到一个终端 19 | { 20 | fprintf(stderr, "You are not a terminal, OK.\n"); //错误信息输出到标准错误流 21 | } 22 | 23 | input = fopen("/dev/tty", "r"); //从终端设备读取输入 24 | output = fopen("/dev/tty", "w"); //向终端设备输出 25 | 26 | if (!input || !output) //判断能否打开终端设备 27 | { 28 | fprintf(stderr, "Unable to open /dev/tty\n"); 29 | exit (1); 30 | } 31 | 32 | do 33 | { 34 | choice = getchoice("Please select an action", menu, input, output); //显示菜单信息,并等待用户输入菜单选项首字母 35 | printf("You have chosen: %c\n", choice); //默认输出到屏幕上 36 | } while(choice != 'q'); //直到用户输入q想要退出,否则一直循环 37 | exit (0); 38 | } 39 | 40 | /* 显示菜单,及读取用户输入 */ 41 | int getchoice(char *greet, char *choices[], FILE *in, FILE *out) 42 | { 43 | int chosen = 0; 44 | int selected; 45 | char **option; 46 | 47 | do //不断循环直到用户输入正确的选项 48 | { 49 | fprintf(out, "Choice: %s\n", greet); //输出到终端设备 50 | option = choices; 51 | while (*option) //通过一个while循环,将字符串数组中的所有内容显示出来 52 | { 53 | fprintf(out, "%s\n", *option); 54 | option++; 55 | } 56 | 57 | do 58 | { 59 | selected = fgetc(in); //从终端读取用户输入 60 | } while (selected == '\n'); 61 | 62 | option = choices; 63 | while (*option) 64 | { 65 | if (selected == *option[0]) //判断用户输入是否符合菜单中某个选项 66 | { 67 | chosen = 1; 68 | break; 69 | } 70 | option++; 71 | } 72 | if (!chosen) 73 | { 74 | fprintf(out, "Incorrect choice, select again\n"); 75 | } 76 | } while(!chosen); 77 | return selected; 78 | } 79 | -------------------------------------------------------------------------------- /Chapter05/menu4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/menu4 -------------------------------------------------------------------------------- /Chapter05/menu5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/menu5 -------------------------------------------------------------------------------- /Chapter05/password: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/password -------------------------------------------------------------------------------- /Chapter05/password.c: -------------------------------------------------------------------------------- 1 | /* 使用termios结构的密码程序 */ 2 | /* 涉及到一下函数: 3 | int tcgetattr(int fd, struct termios *termios_p); 用来初始化一个与终端对应的termios结构 4 | int tcsetattr(int fd, int actions, const struct termios *termios_p); 重新配置终端接口 5 | 参数actions控制修改方式: 6 | ① TCSANOW:立刻对值进行修改 7 | ② TCSADRAIN:等当前的输出完成之后再对值进行修改 8 | ③ TCSAFLUSH:等当前的输出完成之后再对值进行修改,也丢弃还未从read调用返回的当前可用的任何输入 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define PASSWORD_LEN 8 16 | 17 | int main() 18 | { 19 | struct termios initialrsettings, newrsettings; 20 | char password[PASSWORD_LEN + 1]; 21 | 22 | //调用tcgetattr来获取标准输入的当前设置 23 | tcgetattr(fileno(stdin), &initialrsettings); 24 | 25 | //对原始的设置值做一份副本,以便在程序结束时还原设置 26 | newrsettings = initialrsettings; 27 | newrsettings.c_lflag &= ~ECHO; //使用 X &= ~FLAG 来清除变量中X中的FLAG标志定义的比特,其实等价于 X |= FLAG 28 | 29 | printf("Enter password: "); 30 | 31 | //用newrSETTINGS变量中的值设置属性并读取用户输入的密码 32 | if (tcsetattr(fileno(stdin), TCSAFLUSH, &newrsettings) != 0) //用TCSAFLUSH丢弃用户在程序准备好读取数据之前输入的任何内容 33 | { 34 | fprintf(stderr, "Counld not set attributes\n"); 35 | } 36 | else 37 | { 38 | fgets(password, PASSWORD_LEN, stdin); 39 | //用initialrsettings还原原来的终端设置值 40 | tcsetattr(fileno(stdin), TCSANOW, &initialrsettings); 41 | fprintf(stdout, "\nYou entered %s\n", password); 42 | } 43 | exit (0); 44 | } 45 | -------------------------------------------------------------------------------- /Chapter05/sizeterm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter05/sizeterm -------------------------------------------------------------------------------- /Chapter05/sizeterm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 该程序用到的系统函数为: 7 | int setupterm(char *term, int fd, int *errret); 8 | term:将当前终端类型值设置为参数term指向的值 9 | fd:文件描述符 10 | errret:函数的返回值保存在该参数指向的整型变量中 11 | 该函数将当前终端类型设置为参数term执行的值 12 | 13 | int tigetnum(char *capname); 14 | capname:terminfo中数据项的名称 15 | 该函数返回数值功能标志 16 | */ 17 | 18 | int main() 19 | { 20 | int nrows, ncolumns; 21 | 22 | setupterm(NULL, fileno(stdout), (int *)0); 23 | nrows = tigetnum("lines"); 24 | ncolumns = tigetnum("cols"); 25 | printf("This terminal has %d cloumns and %d rows\n", ncolumns, nrows); 26 | exit (0); 27 | } 28 | -------------------------------------------------------------------------------- /Chapter06/CD_APP/curses_cd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/CD_APP/curses_cd -------------------------------------------------------------------------------- /Chapter06/CD_APP/title.cdb: -------------------------------------------------------------------------------- 1 | CD123,Cool sax,Jazz,Bix 2 | CD234,Classic violin,Classical,Bach 3 | CD999, Test, Jazz, shangchao 4 | -------------------------------------------------------------------------------- /Chapter06/CD_APP/tracks.cdb: -------------------------------------------------------------------------------- 1 | CD234,1,Sonata in D minor 2 | CD123,1,another jazz 3 | CD123,2,other jazz 4 | CD999,1,fuck 5 | CD999,2,fuck2 6 | CD999,3,fuck3 7 | -------------------------------------------------------------------------------- /Chapter06/color: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/color -------------------------------------------------------------------------------- /Chapter06/color.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | /* 本程序使用的函数有: 8 | bool has_colors(void); //判断终端是否支持色彩显示 9 | int start_color(void); //该函数用来初始化颜色显示功能 10 | int init_pair(short pair_number, short foreground, short background); //对颜色组合进行初始化 11 | int COLOR_PAIR(int pair_number); //将颜色组合当做属性来访问 12 | 13 | 本程序使用到的全局变量有: 14 | COLORS: 当前终端可用颜色数目的最大值 15 | COLOR_PAIRS:当前终端支持的颜色组合的最大值 16 | */ 17 | 18 | int main() 19 | { 20 | int i; 21 | 22 | initscr(); 23 | 24 | /* 首先检查运行该程序的终端是否支持彩色显示 */ 25 | if (!has_colors()) 26 | { 27 | endwin(); 28 | fprintf(stderr, "Error - no color support on this terminal\n"); 29 | exit (1); 30 | } 31 | 32 | /* 采用色彩显示 */ 33 | if (start_color() != OK) 34 | { 35 | endwin(); 36 | fprintf(stderr, "Error - could not initialize colors\n"); 37 | exit (2); 38 | } 39 | 40 | /* 打印出终端可用颜色数目的最大值,及支持的颜色组合的最大值 */ 41 | clear(); 42 | mvprintw(5, 5, "There are %d COLORS, and %d COLOR_PAIRS available", COLORS, COLOR_PAIRS); 43 | refresh(); 44 | 45 | /* 创建7个颜色组合,并通过for循环依次显示 */ 46 | init_pair(1, COLOR_RED, COLOR_BLACK); 47 | init_pair(2, COLOR_RED, COLOR_GREEN); 48 | init_pair(3, COLOR_GREEN, COLOR_RED); 49 | init_pair(4, COLOR_YELLOW, COLOR_BLUE); 50 | init_pair(5, COLOR_BLACK, COLOR_WHITE); 51 | init_pair(6, COLOR_MAGENTA, COLOR_BLUE); 52 | init_pair(7, COLOR_CYAN, COLOR_WHITE); 53 | 54 | for (i = 1;i <= 7;i++) 55 | { 56 | attroff(A_BOLD); 57 | attrset(COLOR_PAIR(i)); 58 | mvprintw(5 + i, 5 , "color pair %d" , i); 59 | attrset(COLOR_PAIR(i) | A_BOLD); 60 | mvprintw(5 + i, 25, "Bold color pair %d", i); 61 | refresh(); 62 | sleep(1); 63 | } 64 | endwin(); 65 | exit (EXIT_SUCCESS); 66 | } 67 | -------------------------------------------------------------------------------- /Chapter06/ipmode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/ipmode -------------------------------------------------------------------------------- /Chapter06/ipmode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define PW_LEN 256 7 | #define NAME_LEN 256 8 | 9 | int main() 10 | { 11 | char name[NAME_LEN]; 12 | char password[PW_LEN]; 13 | const char *real_password = "xyzzy"; 14 | int i = 0; 15 | 16 | initscr(); 17 | 18 | move(5,10); 19 | printw("%s","Please login: "); 20 | 21 | move(7,10); 22 | printw("%s","User name: "); 23 | getstr(name); //输入用户名字 24 | 25 | move(8,10); 26 | printw("%s","Password: "); 27 | refresh(); 28 | 29 | cbreak(); 30 | noecho(); //关闭回显,这样在输入密码时,就不会显示在屏幕上 31 | 32 | memset(password, '\0', sizeof(password)); //设置一块内存区域用于接受用户输入的密码 33 | while (i < PW_LEN) 34 | { 35 | password[i] = getch(); //读取键盘输入的字符 36 | if (password[i] == '\n') 37 | break; 38 | 39 | move(8,20+i); 40 | addch('*'); //在屏幕上输出*号,来表示加密 密码 41 | refresh(); 42 | i++; 43 | } 44 | 45 | /* 打开回显,并判断用户输入的密码是否正确,并给出验证信息 */ 46 | echo(); //重新打开键盘回显 47 | nocbreak(); 48 | 49 | move(11,10); 50 | if (strncmp(real_password, password, strlen(real_password)) == 0) //strncmp函数相对来说更安全,应为提供了最长字符限制 51 | { 52 | printw("%s", "Correct"); 53 | } 54 | else 55 | { 56 | printw("%s", "Wrong"); 57 | } 58 | printw("%s"," password"); 59 | refresh(); 60 | sleep(2); 61 | 62 | endwin(); 63 | exit(EXIT_SUCCESS); 64 | } 65 | -------------------------------------------------------------------------------- /Chapter06/keypad: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/keypad -------------------------------------------------------------------------------- /Chapter06/keypad.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 该程序演示keypad模式的用法:按下Esc键后,程序将在一段延时里判断这个Esc是一个Escape转义序列还是一个单独的按键 */ 6 | 7 | #define LOCAL_ESCAPE_KEY 27 8 | 9 | int main() 10 | { 11 | int key; 12 | 13 | initscr(); 14 | crmode(); 15 | keypad(stdscr, TRUE); 16 | 17 | /* 关闭回显功能以防止在你按下方向键时发生移动,然后清屏并显示一些文本 */ 18 | noecho(); 19 | clear(); 20 | mvprintw(5, 5, "Key pad demonstration. Press 'q' to quit"); 21 | move(7, 5); 22 | 23 | refresh(); 24 | key = getch(); //获取用户按下的按键 25 | 26 | while (key != ERR && key != 'q') 27 | { 28 | move(7, 5); 29 | clrtoeol(); 30 | 31 | if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z')) //判断用户按下的是不是常规的字母按键 32 | { 33 | printw("Key was %c", (char)key); 34 | } 35 | else 36 | { 37 | switch(key) //检查有可能是哪种转义序列 38 | { 39 | case LOCAL_ESCAPE_KEY: printw("%s", "Escape key");break; 40 | case KEY_END: printw("%s", "END key"); break; 41 | case KEY_BEG: printw("%s", "BEGINNING key");break; 42 | case KEY_RIGHT: printw("%s", "RIGHT key");break; 43 | case KEY_LEFT: printw("%s", "LEFT key");break; 44 | case KEY_UP: printw("%s", "UP key");break; 45 | case KEY_DOWN: printw("%s", "DOWN key");break; 46 | default: printw("Unmatched - %d", key);break; 47 | } 48 | } 49 | refresh(); 50 | key = getch(); 51 | } 52 | endwin(); 53 | exit (EXIT_SUCCESS); 54 | } 55 | -------------------------------------------------------------------------------- /Chapter06/moveadd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/moveadd -------------------------------------------------------------------------------- /Chapter06/moveadd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | const char witch_one[] = " First Witch"; 10 | const char witch_two[] = " Second Witch "; 11 | const char *scan_ptr; 12 | 13 | initscr(); 14 | 15 | move(5,15); 16 | attron(A_BOLD); //开启文本属性——加粗显示 17 | printw("%s","Macbeth"); 18 | attroff(A_BOLD); //关闭文本属性 19 | refresh(); 20 | sleep(3); 21 | 22 | move(8,15); 23 | attron(A_STANDOUT); //开启文本属性——突出/强调显示,字符终端最亮 24 | printw("%s","Thunder and Lightning"); 25 | attroff(A_STANDOUT); //关闭文本属性 26 | refresh(); 27 | sleep(3); 28 | 29 | move(10,10); 30 | printw("%s","When shall we three meet again"); 31 | move(11,23); 32 | printw("%s","In thunder, lighting, or in rain?"); 33 | move(13,10); 34 | printw("%s", "When the hurlyburly's done,"); 35 | move(14,23); 36 | printw("%s","When the battle's lost and won."); 37 | refresh(); 38 | sleep(3); 39 | 40 | attron(A_DIM); //开启文本属性——半亮显示 41 | scan_ptr = witch_one + strlen(witch_one) -1; 42 | while (scan_ptr != witch_one) 43 | { 44 | move(10,10); 45 | insch(*scan_ptr--); //通过指针显示预先定义的字符串 46 | } 47 | scan_ptr = witch_two + strlen(witch_two) - 1; 48 | while (scan_ptr != witch_two) 49 | { 50 | move(13,10); 51 | insch(*scan_ptr--); 52 | } 53 | 54 | attroff(A_DIM); 55 | refresh(); 56 | sleep(3); 57 | 58 | move(LINES -1 , COLS -1); //将光标移动到屏幕的最后 59 | refresh(); 60 | sleep(3); 61 | 62 | endwin(); 63 | exit(EXIT_SUCCESS); 64 | } 65 | -------------------------------------------------------------------------------- /Chapter06/multiw1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/multiw1 -------------------------------------------------------------------------------- /Chapter06/multiw1.c: -------------------------------------------------------------------------------- 1 | include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | WINDOW *new_window_ptr; 8 | WINDOW *popup_window_ptr; 9 | 10 | int x_loop; 11 | int y_loop; 12 | char a_letter = 'a'; 13 | 14 | initscr(); 15 | 16 | /* 用字符填充基本窗口,然后刷新物理屏幕 */ 17 | move(5,5); 18 | printw("%s","Testing multiple windows"); 19 | refresh(); 20 | 21 | for (y_loop = 0; y_loop < LINES -1 ;y_loop++) 22 | { 23 | for (x_loop = 0;x_loop < COLS - 1;x_loop++) 24 | { 25 | mvwaddch(stdscr, y_loop, x_loop, a_letter); 26 | a_letter++; 27 | if (a_letter > 'z') 28 | a_letter = 'a'; 29 | } 30 | } 31 | /* 刷新屏幕 */ 32 | refresh(); 33 | sleep(2); 34 | 35 | /* 创建一个尺寸为10*20的新窗口,并添加一些文本,然后刷新物理屏幕 */ 36 | new_window_ptr = newwin(10,20,5,5); 37 | mvwprintw(new_window_ptr, 2, 2, "%s", "Hello World"); 38 | mvwprintw(new_window_ptr, 5, 2, "%s", "Notice how very long lines wrap inside the window"); 39 | wrefresh(new_window_ptr); //刷新窗口 40 | sleep(2); 41 | 42 | /* 重新将整个屏幕填充成数字 */ 43 | a_letter = '0'; 44 | for (y_loop = 0; y_loop < LINES -1; y_loop++) 45 | { 46 | for (x_loop = 0;x_loop < COLS - 1;x_loop++) 47 | { 48 | mvwaddch(stdscr, y_loop, x_loop, a_letter); 49 | a_letter++; 50 | if (a_letter > '9') 51 | a_letter = '0'; 52 | } 53 | } 54 | refresh(); 55 | sleep(2); 56 | 57 | /* 此时,只调用wrefresh来刷新窗口,则什么也不会发生,因为上面的改动是在stdscr中发生,而不是在新窗口发生的 */ 58 | wrefresh(new_window_ptr); 59 | sleep(2); 60 | /* 使用touchwin函数强制curses重新绘制窗口,即使窗口的内容没有发生变化 */ 61 | touchwin(new_window_ptr); 62 | wrefresh(new_window_ptr); 63 | sleep(2); 64 | 65 | /* 再增加另一个加框的重叠窗口 */ 66 | popup_window_ptr= newwin(10,20,8,8); 67 | box(popup_window_ptr, '|', '-'); //使用竖线和短横线作为边框 68 | mvwprintw(popup_window_ptr,5,2,"%s","Pop Up Window"); 69 | wrefresh(popup_window_ptr); 70 | sleep(2); 71 | 72 | /* 在屏幕上轮流显示这两个新窗口 */ 73 | touchwin(new_window_ptr); 74 | wrefresh(new_window_ptr); 75 | sleep(2); 76 | wclear(new_window_ptr); 77 | wrefresh(new_window_ptr); 78 | sleep(2); 79 | delwin(new_window_ptr); 80 | touchwin(popup_window_ptr); 81 | wrefresh(popup_window_ptr); 82 | sleep(2); 83 | delwin(popup_window_ptr); 84 | touchwin(stdscr); 85 | refresh(); 86 | sleep(2); 87 | endwin(); 88 | exit (EXIT_SUCCESS); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /Chapter06/pad: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/pad -------------------------------------------------------------------------------- /Chapter06/pad.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | /* curses提供了一个特殊的数据结构pad来建立一种逻辑屏幕,该屏幕的尺寸大于正常物理屏幕。这样将逻辑屏幕的部分或全部内容输出到 7 | 物理屏幕上,效果会更好。 8 | 9 | 创建pad的方式为: 10 | WINDOW *newpad(int number_of_lines, int number_of_columns); 11 | 12 | 删除pad的方式为: 13 | delwin,与删除正常的窗口一样 14 | 15 | pad使用不同的刷新操作,因为一个pad并不局限于某个特定的屏幕位置,必须指定希望放到屏幕上的pad范围及其放置在屏幕上的位置: 16 | int prefresh(WINDON *pad_ptr, int pad_row, int pad_column, int screen_row_min, int screen_col_min, int screen_row_max, int screen_col_max); 17 | 18 | 上面的函数的作用为将pad从坐标(pad_row,pad_col)开始的区域写到屏幕上的指定区域,那个区域的范围是:(screen_row_min,screen_col_min) 到 (screen_row_max,screen_col_max) 19 | 20 | */ 21 | 22 | int main() 23 | { 24 | /* 首先初始化pad结构,然后创建一个pad,之后用字符串填充这个pad */ 25 | WINDOW *pad_ptr; 26 | int x, y; 27 | int pad_lines; 28 | int pad_cols; 29 | char disp_char; 30 | 31 | initscr(); 32 | pad_lines = LINES + 50; 33 | pad_cols = COLS + 50; 34 | pad_ptr = newpad(pad_lines, pad_cols); 35 | disp_char = 'a'; 36 | 37 | for (x = 0; x < pad_lines; x++) 38 | { 39 | for (y = 0; y < pad_cols; y++) 40 | { 41 | mvwaddch(pad_ptr, x, y, disp_char); 42 | if (disp_char == 'z') 43 | { 44 | disp_char = 'a'; 45 | } 46 | else 47 | { 48 | disp_char++; 49 | } 50 | } 51 | } 52 | 53 | /* 将pad的不同区域绘制到屏幕的不同位置上 */ 54 | prefresh(pad_ptr, 5, 7, 2, 2, 9, 9); 55 | sleep(1); 56 | prefresh(pad_ptr, LINES+5, COLS+7, 5,5, 21, 19); 57 | sleep(1); 58 | delwin(pad_ptr); 59 | endwin(); 60 | exit (EXIT_SUCCESS); 61 | } 62 | -------------------------------------------------------------------------------- /Chapter06/screen1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/screen1 -------------------------------------------------------------------------------- /Chapter06/screen1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | initscr(); //在开始使用curses库之前,先进行初始化 8 | move(5,15); //将光标移动到(5,15)处 9 | printw("%s", "Hello, World"); 10 | refresh(); //刷新物理屏幕 11 | sleep(2); 12 | endwin(); //结束使用后,恢复原先的设置 13 | exit(EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/subsc1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter06/subsc1 -------------------------------------------------------------------------------- /Chapter06/subsc1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 在这个函数中,使用子窗口来卷动另一窗口里的部分内容,这也是子窗口最主要的用途 */ 7 | 8 | int main() 9 | { 10 | WINDOW *sub_window_ptr; 11 | int x_loop; 12 | int y_loop; 13 | int counter; 14 | char a_letter = '1'; 15 | 16 | initscr(); 17 | 18 | for (y_loop = 0;y_loop < LINES - 1;y_loop++) 19 | { 20 | for (x_loop = 0;x_loop < COLS - 1;x_loop++) 21 | { 22 | mvwaddch(stdscr, y_loop, x_loop, a_letter); 23 | a_letter++; 24 | if (a_letter > '9') 25 | { 26 | a_letter = '1'; 27 | } 28 | } 29 | } 30 | /* 创建一个新的卷动子窗口,且必须在刷新屏幕之前对父窗口调用touchwin函数 */ 31 | sub_window_ptr = subwin(stdscr, 10, 20, 10, 10); 32 | scrollok(sub_window_ptr, 1); 33 | 34 | touchwin(stdscr); 35 | refresh(); 36 | sleep(1); 37 | 38 | /* 删除子窗口中的内容,重新输出一些文字 */ 39 | werase(sub_window_ptr); 40 | mvwprintw(sub_window_ptr,2, 0, "%s", "This window will now scroll"); 41 | wrefresh(sub_window_ptr); 42 | sleep(1); 43 | 44 | for (counter = 1;counter < 10; counter++) 45 | { 46 | wprintw(sub_window_ptr, "%s", "This text is both wrapping and scrolling."); 47 | wrefresh(sub_window_ptr); 48 | sleep(1); 49 | } 50 | 51 | 52 | delwin(sub_window_ptr); 53 | 54 | touchwin(stdscr); 55 | refresh(); 56 | sleep(1); 57 | endwin(); 58 | exit (EXIT_SUCCESS); 59 | } 60 | -------------------------------------------------------------------------------- /Chapter07/CD_APP/Makefile: -------------------------------------------------------------------------------- 1 | all: application 2 | 3 | INCLUDE=/usr/include/gdbm 4 | LIBS=-lgdbm_compat -lgdbm 5 | 6 | CFLAGS= 7 | 8 | app_ui.o: app_ui.c cd_data.h 9 | gcc $(CFLAGS) -c app_ui.c 10 | 11 | cd_access.o: cd_access.c cd_data.h 12 | gcc $(CFLAGS) -I$(INCLUDE) -c cd_access.c 13 | 14 | application: app_ui.o cd_access.o 15 | gcc $(CFLAGS) -o application app_ui.o cd_access.o $(LIBS) 16 | 17 | clean: 18 | rm -f application *.o 19 | 20 | nodbmfiles: 21 | rm -f *.dir *.pag 22 | -------------------------------------------------------------------------------- /Chapter07/CD_APP/app_ui.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/CD_APP/app_ui.o -------------------------------------------------------------------------------- /Chapter07/CD_APP/application: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/CD_APP/application -------------------------------------------------------------------------------- /Chapter07/CD_APP/cd_access.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/CD_APP/cd_access.o -------------------------------------------------------------------------------- /Chapter07/CD_APP/cd_data.h: -------------------------------------------------------------------------------- 1 | /* 该头文件用于 定义数据的结构和用于访问这些结构的函数 */ 2 | 3 | /* The catalog table */ 4 | #define CAT_CAT_LEN (30) 5 | #define CAT_TITLE_LEN (70) 6 | #define CAT_TYPE_LEN (30) 7 | #define CAT_ARTIST_LEN (70) 8 | 9 | typedef struct 10 | { 11 | char catalog[CAT_CAT_LEN + 1]; 12 | char title[CAT_TITLE_LEN + 1]; 13 | char type[CAT_TYPE_LEN + 1]; 14 | char artist[CAT_ARTIST_LEN + 1]; 15 | } cdc_entry; 16 | 17 | 18 | /* The tracks table */ 19 | #define TRACK_CAT_LEN CAT_CAT_LEN 20 | #define TRACK_TTEXT_LEN (70) 21 | 22 | typedef struct 23 | { 24 | char catalog[TRACK_CAT_LEN + 1]; 25 | int track_no; //该曲目的编号 26 | char track_txt[TRACK_TTEXT_LEN + 1]; 27 | } cdt_entry; 28 | 29 | /* 下面介绍用于访问数据结构的函数 */ 30 | 31 | /* 初始化和终止函数 */ 32 | int database_initialize(const int new_database); 33 | void database_close(void); 34 | 35 | /* 两个取数据函数 */ 36 | cdc_entry get_cdc_entry(const char *cd_catalog_ptr); 37 | cdt_entry get_cdt_entry(const char *cd_catalog_ptr, const int track_no); 38 | 39 | /* 两个增加数据的函数 */ 40 | int add_cdc_entry(const cdc_entry entry_to_add); 41 | int add_cdt_entry(const cdt_entry entry_to_add); 42 | 43 | /* 两个删除数据的函数 */ 44 | int del_cdc_entry(const char *cd_catalog_ptr); 45 | int del_cdt_entry(const char *cd_catalog_ptr, const int track_no); 46 | 47 | /* (根据标题)检索函数 */ 48 | cdc_entry search_cdc_entry(const char *cd_catalog_ptr, int *first_call_ptr); 49 | -------------------------------------------------------------------------------- /Chapter07/CD_APP/cdc_data.dir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/CD_APP/cdc_data.dir -------------------------------------------------------------------------------- /Chapter07/CD_APP/cdc_data.pag: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/CD_APP/cdc_data.pag -------------------------------------------------------------------------------- /Chapter07/CD_APP/cdt_data.dir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/CD_APP/cdt_data.dir -------------------------------------------------------------------------------- /Chapter07/CD_APP/cdt_data.pag: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/CD_APP/cdt_data.pag -------------------------------------------------------------------------------- /Chapter07/dbm1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/dbm1 -------------------------------------------------------------------------------- /Chapter07/dbm1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define TEST_DB_FILE "/tmp/dbm1_test" 9 | #define ITEMS_USED (3) 10 | 11 | struct test_data 12 | { 13 | char misc_chars[15]; 14 | int any_integer; 15 | char more_chars[21]; 16 | }; 17 | 18 | int main() 19 | { 20 | struct test_data items_to_store[ITEMS_USED]; 21 | struct test_data item_retrieved; 22 | 23 | /* 定义关键字字符串 */ 24 | char key_to_use[20]; 25 | int i, result; 26 | 27 | /* 定义datum结构,分别表示关键字(索引)和数据内容 */ 28 | datum key_datum; 29 | datum data_datum; 30 | 31 | DBM *dbm_ptr; 32 | 33 | /* 打开测试数据库用来读写 */ 34 | dbm_ptr = dbm_open(TEST_DB_FILE, O_RDWR | O_CREAT, 0666); 35 | if (!dbm_ptr) 36 | { 37 | fprintf(stderr, "Failed to open database\n"); 38 | exit (EXIT_FAILURE); 39 | } 40 | 41 | /* 添加一些数据到items_to_store结构中 */ 42 | memset(items_to_store, '\0', sizeof(items_to_store)); 43 | strcpy(items_to_store[0].misc_chars, "First!"); 44 | items_to_store[0].any_integer = 47; 45 | strcpy(items_to_store[0].more_chars, "foo"); 46 | 47 | strcpy(items_to_store[1].misc_chars, "bar"); 48 | items_to_store[1].any_integer = 13; 49 | strcpy(items_to_store[1].more_chars, "unlucky?"); 50 | 51 | strcpy(items_to_store[2].misc_chars, "Third"); 52 | items_to_store[2].any_integer = 3; 53 | strcpy(items_to_store[2].more_chars, "baz"); 54 | 55 | /* 为每个数据项建立一个供以后引用的关键字(索引)*/ 56 | for (i = 0;i < ITEMS_USED;i++) 57 | { 58 | sprintf(key_to_use, "%c%c%d", items_to_store[i].misc_chars[0], items_to_store[i].more_chars[0], items_to_store[i].any_integer); 59 | key_datum.dptr = (void *)key_to_use; 60 | key_datum.dsize = strlen(key_to_use); 61 | data_datum.dptr = (void *)&items_to_store[i]; 62 | data_datum.dsize = sizeof(struct test_data); 63 | 64 | result = dbm_store(dbm_ptr, key_datum, data_datum, DBM_REPLACE); 65 | if (result != 0) 66 | { 67 | fprintf(stderr, "dbm_store failed on key %s\n", key_to_use); 68 | exit (2); 69 | } 70 | } 71 | 72 | /* 查看是否可以检索新存入的数据 */ 73 | /* 在一面一行语句中,检索的是原来存入的第一个数据项 */ 74 | sprintf(key_to_use, "Ff%d", 47); 75 | key_datum.dptr = key_to_use; 76 | key_datum.dsize = strlen(key_to_use); 77 | 78 | data_datum = dbm_fetch(dbm_ptr, key_datum); 79 | 80 | if (data_datum.dptr) 81 | { 82 | printf("Data retrieved\n"); 83 | memcpy(&item_retrieved, data_datum.dptr, data_datum.dsize); 84 | printf("Retrieved item - %s %d %s\n", item_retrieved.misc_chars, item_retrieved.any_integer, item_retrieved.more_chars); 85 | } 86 | else 87 | { 88 | printf("No data found for key %s\n", key_to_use); 89 | } 90 | dbm_close(dbm_ptr); 91 | exit (EXIT_SUCCESS); 92 | } 93 | -------------------------------------------------------------------------------- /Chapter07/dbm2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/dbm2 -------------------------------------------------------------------------------- /Chapter07/lock1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/lock1 -------------------------------------------------------------------------------- /Chapter07/lock1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 该程序演示了锁文件的使用 */ 8 | /* 使用在fcntl.h中定义的open系统调用,并且带有标志O_CREAT、O_EXCL, 9 | 能够以一个原子操作同时完成两项工作: 10 | ① 确定文件不存在 11 | ② 创建该文件 12 | */ 13 | 14 | int main() 15 | { 16 | int file_desc; 17 | int save_errno; 18 | 19 | file_desc = open("/tmp/LCK.test", O_RDWR | O_CREAT | O_EXCL, 0444); 20 | if (file_desc == -1) 21 | { 22 | save_errno = errno; 23 | printf("Open failed with error %d\n", save_errno); 24 | } 25 | else 26 | { 27 | printf("Open successed\n"); 28 | } 29 | exit (EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /Chapter07/lock2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/lock2 -------------------------------------------------------------------------------- /Chapter07/lock2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 该程序演示了临界区的使用: 8 | 临界区:一个程序在执行时,只需独占的占用某一资源很短的时间。 9 | 10 | 需要在程序进入临界区之前使用open系统调用创建锁文件,然后在 11 | 退出临界区时用unlink系统调用删除该锁文件 12 | */ 13 | 14 | const char *lock_file = "/tmp/LCK.test2"; 15 | 16 | int main() 17 | { 18 | int file_desc; 19 | int tries = 10; 20 | 21 | while (tries--) 22 | { 23 | file_desc = open(lock_file, O_RDWR | O_CREAT | O_EXCL, 0444); 24 | if (file_desc == -1) 25 | { 26 | printf("%d - Lock already present\n", getpid()); 27 | sleep(3); 28 | } 29 | else 30 | { 31 | /* 临界区从此处开始 */ 32 | printf("%d - I have exclusive access\n", getpid()); 33 | sleep(1); 34 | (void)close(file_desc); 35 | /* 退出临界区时,使用unlink函数删除该锁文件 */ 36 | (void)unlink(lock_file); 37 | sleep(2); 38 | } 39 | } 40 | exit (EXIT_SUCCESS); 41 | } 42 | -------------------------------------------------------------------------------- /Chapter07/lock3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/lock3 -------------------------------------------------------------------------------- /Chapter07/lock3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 该程序要和lock4.c程序配合使用 */ 7 | 8 | /* 该程序使用了fcntl函数,该函数对一个打开的文件描述符进行操作,并能根据command参数的设置完成不同的任务 9 | 10 | int fcntl(int fildes, int command,……); 11 | 对于第二个参数,有3个用于文件锁定的命令选项: 12 | ① F_GETLK 13 | ② F_SETLK 14 | ③ F_SETLKW 15 | 当使用上面这些命令时,第三个参数必须是指向flock结构的指针。 16 | 此时,该函数原型为: 17 | 18 | int fcntl(int fildes, int command, struct flock *flock_structure); 19 | */ 20 | 21 | const char *test_file = "/tmp/test_lock"; 22 | 23 | int main() 24 | { 25 | int file_desc; 26 | int byte_count; 27 | char *byte_to_write = "A"; 28 | struct flock region_1; 29 | struct flock region_2; 30 | int res; 31 | 32 | /* 打开一个文件描述符 */ 33 | file_desc = open(test_file, O_RDWR | O_CREAT, 0666); 34 | if (!file_desc) 35 | { 36 | fprintf(stderr, "Unable to open %s for read/write\n", test_file); 37 | exit (EXIT_SUCCESS); 38 | } 39 | 40 | /* 向文件添加一些数据 */ 41 | for (byte_count = 0;byte_count < 100; byte_count++) 42 | { 43 | (void)write(file_desc, byte_to_write, 1); 44 | } 45 | 46 | /* 把文件的10-30字节设为区域1,并在其上设置共享锁(读锁)*/ 47 | region_1.l_type = F_RDLCK; 48 | region_1.l_whence = SEEK_SET; 49 | region_1.l_start = 10; 50 | region_1.l_len = 20; 51 | 52 | /* 把文件的40-50字节设为区域2,并在其上设置独占锁(写锁)*/ 53 | region_2.l_type = F_WRLCK; 54 | region_2.l_whence = SEEK_SET; 55 | region_2.l_start = 40; 56 | region_2.l_len = 10; 57 | 58 | /* 锁定文件 */ 59 | printf("Process %d locking file\n", getpid()); 60 | res = fcntl(file_desc, F_SETLK, ®ion_1); 61 | if (res == -1) 62 | { 63 | fprintf(stderr, "Failed to lock region 1\n"); 64 | } 65 | res = fcntl(file_desc, F_SETLK, ®ion_2); 66 | if (res == -1) 67 | { 68 | fprintf(stderr, "Failed to lock region 2\n"); 69 | } 70 | 71 | sleep(60); 72 | printf("Process %d closing file\n", getpid()); 73 | close(file_desc); 74 | exit (EXIT_SUCCESS); 75 | } 76 | -------------------------------------------------------------------------------- /Chapter07/lock4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/lock4 -------------------------------------------------------------------------------- /Chapter07/lock4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 编写一个程序用来测试可能会用在文件不同区域上的各种类型的锁 */ 7 | /* 本程序用来测试lock3.c,先运行lock3.c(通过键入./loc3 & 使其后台运行),再运行lock4.c */ 8 | 9 | const char *test_file = "/tmp/test_lock"; 10 | 11 | #define SIZE_TO_TRY 5 12 | 13 | void show_lock_info(struct flock *to_show); 14 | 15 | int main() 16 | { 17 | int file_desc; 18 | int res; 19 | struct flock region_to_test; 20 | int start_byte; 21 | 22 | /* 打开一个文件描述符 */ 23 | file_desc = open(test_file, O_RDWR | O_CREAT, 0666); 24 | if (!file_desc) 25 | { 26 | fprintf(stderr, "Unable to open %s for read/write", test_file); 27 | exit (EXIT_FAILURE); 28 | } 29 | 30 | /* 将文件test_lock中的每5个字节分为1组,并为其设置一个区域结构来测试锁, 31 | 之后通过使用该结构来判断对应区域是否可以被加独占锁 或者共享锁 */ 32 | for (start_byte = 0;start_byte < 99; start_byte += SIZE_TO_TRY) 33 | { 34 | /* 设置希望测试的文件区域 */ 35 | region_to_test.l_type = F_WRLCK; 36 | region_to_test.l_whence = SEEK_SET; 37 | region_to_test.l_start = start_byte; 38 | region_to_test.l_len = SIZE_TO_TRY; 39 | region_to_test.l_pid = -1; 40 | 41 | printf("Testing F_WRLCK on region from %d to %d\n", start_byte, start_byte + SIZE_TO_TRY); 42 | 43 | /* 测试文件上的锁 */ 44 | res = fcntl(file_desc, F_GETLK, ®ion_to_test); 45 | if (res == -1) 46 | { 47 | fprintf(stderr, "F_GETLK failed\n"); 48 | exit (EXIT_FAILURE); 49 | } 50 | if (region_to_test.l_pid != -1) 51 | { 52 | printf("Lock would fail. F_GETLK returned: \n"); 53 | show_lock_info(®ion_to_test); 54 | } 55 | else 56 | { 57 | printf("F_WRLCK - Lock would succeed\n"); 58 | } 59 | 60 | /* 用共享(读)锁重复测试一次,再次设置希望测试的文件区域 */ 61 | region_to_test.l_type = F_RDLCK; 62 | region_to_test.l_whence = SEEK_SET; 63 | region_to_test.l_start = start_byte; 64 | region_to_test.l_len = SIZE_TO_TRY; 65 | region_to_test.l_pid = -1; 66 | printf("Testing F_RDLCK on region from %d to %d\n", start_byte, start_byte + SIZE_TO_TRY); 67 | 68 | /* 再次测试文件上的锁 */ 69 | res = fcntl(file_desc, F_GETLK, ®ion_to_test); 70 | if (res == -1) 71 | { 72 | fprintf(stderr, "F_GETLK failed\n"); 73 | exit (EXIT_FAILURE); 74 | } 75 | if (region_to_test.l_pid != -1) 76 | { 77 | printf("Lock would fail. F_GETLK returned.\n"); 78 | show_lock_info(®ion_to_test); 79 | } 80 | else 81 | { 82 | printf("F_RDLCK - Lock would succeed\n"); 83 | } 84 | } 85 | close(file_desc); 86 | exit (EXIT_SUCCESS); 87 | } 88 | 89 | 90 | void show_lock_info(struct flock *to_show) 91 | { 92 | printf("\tl_type %d, ", to_show->l_type); 93 | printf("l_whence %d ", to_show->l_whence); 94 | printf("l_start %d ", (int)to_show->l_start); 95 | printf("l_len %d ", (int)to_show->l_len); 96 | printf("l_pid %d\n", to_show->l_pid); 97 | } 98 | -------------------------------------------------------------------------------- /Chapter07/lock5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/lock5 -------------------------------------------------------------------------------- /Chapter07/memory1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/memory1 -------------------------------------------------------------------------------- /Chapter07/memory1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 1MB大小 */ 6 | /* 1024B = 1KB, 1024个1KB是1MB */ 7 | #define A_MEGABYTE (1024 * 1024) 8 | 9 | int main() 10 | { 11 | char *some_memory; 12 | int megabyte = A_MEGABYTE; 13 | int exit_code = EXIT_FAILURE; 14 | 15 | /* 使用malloc函数分配空间,并使用强制转换将void *型指针转换为char *型指针 */ 16 | some_memory = (char *)malloc(megabyte); 17 | if (some_memory != NULL) 18 | { 19 | sprintf(some_memory, "Hello World\n"); 20 | printf("%s", some_memory); 21 | exit_code = EXIT_SUCCESS; 22 | } 23 | exit (exit_code); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter07/memory2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/memory2 -------------------------------------------------------------------------------- /Chapter07/memory2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 在这个程序中,将请求比机器的实际物理内存更多的内存 */ 6 | 7 | #define A_MEGABYTE (1024 * 1024) 8 | #define PHY_MEM_MEGS 1024 9 | 10 | int main() 11 | { 12 | char *some_memory; 13 | size_t size_to_allocate = A_MEGABYTE; 14 | int megs_obtained = 0; 15 | 16 | /* 当已分配的内存兆数小于实际物理内存的8倍时循环 */ 17 | while (megs_obtained < (PHY_MEM_MEGS * 8)) 18 | { 19 | some_memory = (char *)malloc(size_to_allocate); 20 | if (some_memory != NULL) 21 | { 22 | /* 分配内存空间加1MB */ 23 | megs_obtained++; 24 | sprintf(some_memory, "Hello World"); 25 | printf("%s - now allocated %d Megabytes\n", some_memory, megs_obtained); 26 | } 27 | else 28 | { 29 | exit (EXIT_FAILURE); 30 | } 31 | } 32 | exit (EXIT_SUCCESS); 33 | } 34 | -------------------------------------------------------------------------------- /Chapter07/memory3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/memory3 -------------------------------------------------------------------------------- /Chapter07/memory3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 该程序不断分配1MB的内存块,并写入字符串,并记录分配了多少GB */ 6 | 7 | #define ONE_M (1024 * 1024) 8 | 9 | int main() 10 | { 11 | char *some_memory; 12 | int size_to_allocate = ONE_M; 13 | int gegas_obtained = 0; 14 | int ms_obtained = 0; 15 | 16 | while (1) 17 | { 18 | for (ms_obtained = 0; ms_obtained < 1024; ms_obtained++) 19 | { 20 | some_memory = (char *)malloc(size_to_allocate); 21 | if (some_memory == NULL) 22 | { 23 | exit (EXIT_FAILURE); 24 | } 25 | else 26 | { 27 | sprintf(some_memory, "Hello, World"); 28 | } 29 | } 30 | gegas_obtained++; 31 | printf("Now allocated %d gegasbytes\n", gegas_obtained); 32 | } 33 | exit (EXIT_SUCCESS); 34 | } 35 | -------------------------------------------------------------------------------- /Chapter07/memory4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/memory4 -------------------------------------------------------------------------------- /Chapter07/memory4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define ONE_K (1024) 4 | 5 | int main() 6 | { 7 | char *some_memory; 8 | char *scan_ptr; 9 | 10 | some_memory = (char *)malloc(ONE_K); 11 | if (some_memory == NULL) 12 | { 13 | exit (EXIT_FAILURE); 14 | } 15 | 16 | scan_ptr = some_memory; 17 | /* while循环中scan_ptr的自增最终会超过1KB的内存 */ 18 | while (1) 19 | { 20 | scan_ptr = '\0'; 21 | scan_ptr++; 22 | } 23 | exit (EXIT_SUCCESS); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter07/memory5a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/memory5a -------------------------------------------------------------------------------- /Chapter07/memory5a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Linux(在GNU C函数的包装下) */ 6 | 7 | int main() 8 | { 9 | char *some_memory = (char *)0; 10 | /* 访问空指针 */ 11 | printf("A read from null %s\n", some_memory); 12 | sprintf(some_memory, "A write to null\n"); 13 | exit (EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter07/memory5b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/memory5b -------------------------------------------------------------------------------- /Chapter07/memory5b.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | char z = *(const char *)0; 8 | printf("I read from location zero\n"); 9 | 10 | exit (EXIT_SUCCESS); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter07/memory6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter07/memory6 -------------------------------------------------------------------------------- /Chapter07/memory6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ONE_K (1024) 5 | 6 | int main() 7 | { 8 | char *some_memory; 9 | int exit_code = EXIT_FAILURE; 10 | 11 | some_memory = (char *)malloc(ONE_K); 12 | 13 | if (some_memory != NULL) 14 | { 15 | free(some_memory); 16 | printf("Memory allocated and freed again\n"); 17 | exit_code = EXIT_SUCCESS; 18 | } 19 | exit (exit_code); 20 | } 21 | -------------------------------------------------------------------------------- /Chapter08/connect1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/connect1 -------------------------------------------------------------------------------- /Chapter08/connect1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | MYSQL *conn_ptr; 9 | 10 | conn_ptr = mysql_init(NULL); 11 | if (!conn_ptr) 12 | { 13 | fprintf(stderr, "mysql_init failed\n"); 14 | return EXIT_FAILURE; 15 | } 16 | 17 | conn_ptr = mysql_real_connect(conn_ptr, "localhost", "rick", "secret", "foo", 0, NULL, 0); 18 | 19 | if (conn_ptr) 20 | { 21 | printf("Connection success\n"); 22 | } 23 | else 24 | { 25 | printf("Connection failed\n"); 26 | } 27 | 28 | mysql_close(conn_ptr); 29 | return EXIT_SUCCESS; 30 | } 31 | -------------------------------------------------------------------------------- /Chapter08/connect2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/connect2 -------------------------------------------------------------------------------- /Chapter08/connect2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | /* 自定义一个连接句柄作为变量 */ 9 | MYSQL my_connection; 10 | 11 | /* 使用非动态分配的连接结构 */ 12 | mysql_init(&my_connection); 13 | 14 | if (mysql_real_connect(&my_connection, "localhost", "rick", "I do not know", "foo", 0, NULL, 0)) 15 | { 16 | printf("Connection success\n"); 17 | mysql_close(&my_connection); 18 | } 19 | else 20 | { 21 | fprintf(stderr, "Connectin failed\n"); 22 | if (mysql_errno(&my_connection)) 23 | { 24 | fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 25 | } 26 | } 27 | return EXIT_SUCCESS; 28 | } 29 | -------------------------------------------------------------------------------- /Chapter08/create_children.sql: -------------------------------------------------------------------------------- 1 | 2 | -- SQL的注释符号有意思 3 | -- Create the table children 4 | -- 5 | 6 | CREATE TABLE children 7 | ( 8 | childno INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY, 9 | fname VARCHAR(30), 10 | age INTEGER 11 | ); 12 | 13 | -- 14 | -- Populate the table 'children' 15 | -- 16 | 17 | INSERT INTO children(childno, fname, age) VALUES(2,'Andrew', 17); 18 | INSERT INTO children(childno, fname, age) VALUES(3,'Gavin', 9); 19 | INSERT INTO children(childno, fname, age) VALUES(4,'Duncan', 6); 20 | INSERT INTO children(childno, fname, age) VALUES(5,'Emma', 4); 21 | INSERT INTO children(childno, fname, age) VALUES(6,'Alex', 15); 22 | INSERT INTO children(childno, fname, age) VALUES(7,'Adrian', 9); 23 | -------------------------------------------------------------------------------- /Chapter08/insert1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/insert1 -------------------------------------------------------------------------------- /Chapter08/insert1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | /* 自定义一个连接句柄作为变量 */ 9 | MYSQL my_connection; 10 | 11 | int res; 12 | 13 | /* 使用非动态分配的连接结构 */ 14 | mysql_init(&my_connection); 15 | 16 | if (mysql_real_connect(&my_connection, "localhost", "rick", "secret", "foo", 0, NULL, 0)) 17 | { 18 | printf("Connection success\n"); 19 | res = mysql_query(&my_connection, "INSERT INTO children(fname, age) VALUES('Ann', 3)"); 20 | 21 | if (!res) 22 | { 23 | printf("Inserted %lu rows\n", (unsigned long)mysql_affected_rows(&my_connection)); 24 | } 25 | else 26 | { 27 | fprintf(stderr, "Insert error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 28 | } 29 | mysql_close(&my_connection); 30 | } 31 | else 32 | { 33 | fprintf(stderr, "Connectin failed\n"); 34 | if (mysql_errno(&my_connection)) 35 | { 36 | fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 37 | } 38 | } 39 | return EXIT_SUCCESS; 40 | } 41 | -------------------------------------------------------------------------------- /Chapter08/insert2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/insert2 -------------------------------------------------------------------------------- /Chapter08/insert2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | /* 自定义一个连接句柄作为变量 */ 9 | MYSQL my_connection; 10 | MYSQL_RES *res_ptr; 11 | MYSQL_ROW sqlrow; 12 | 13 | int res; 14 | 15 | /* 使用非动态分配的连接结构 */ 16 | mysql_init(&my_connection); 17 | 18 | if (mysql_real_connect(&my_connection, "localhost", "rick", "secret", "foo", 0, NULL, 0)) 19 | { 20 | printf("Connection success\n"); 21 | res = mysql_query(&my_connection, "INSERT INTO children(fname, age) VALUES('Robert', 7)"); 22 | 23 | if (!res) 24 | { 25 | printf("Inserted %lu rows\n", (unsigned long)mysql_affected_rows(&my_connection)); 26 | } 27 | else 28 | { 29 | fprintf(stderr, "Insert error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 30 | } 31 | 32 | /* 在插入一行之后,使用 LAST_INSERT_ID()来获得分配的ID */ 33 | res = mysql_query(&my_connection, "SELECT LAST_INSERT_ID()"); 34 | 35 | if (res) 36 | { 37 | printf("SELECT error: %s\n", mysql_error(&my_connection)); 38 | } 39 | else 40 | { 41 | /* 使用mysql_use_resutl()从执行的SELECT语句中获取数据并将它打印出来 */ 42 | res_ptr = mysql_use_result(&my_connection); 43 | if (res_ptr) 44 | { 45 | while ((sqlrow = mysql_fetch_row(res_ptr))) 46 | { 47 | printf("We inserted childno %s\n", sqlrow[0]); 48 | } 49 | mysql_free_result(res_ptr); 50 | } 51 | } 52 | mysql_close(&my_connection); 53 | } 54 | else 55 | { 56 | fprintf(stderr, "Connectin failed\n"); 57 | if (mysql_errno(&my_connection)) 58 | { 59 | fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 60 | } 61 | } 62 | return EXIT_SUCCESS; 63 | } 64 | -------------------------------------------------------------------------------- /Chapter08/select1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/select1 -------------------------------------------------------------------------------- /Chapter08/select1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | MYSQL my_connection; 7 | MYSQL_RES *res_ptr; 8 | MYSQL_ROW sqlrow; 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | int res; 13 | 14 | mysql_init(&my_connection); 15 | /* 与数据库进行连接 */ 16 | if (mysql_real_connect(&my_connection, "localhost", "rick", "secret", "foo", 0, NULL, 0)) 17 | { 18 | printf("Connection success\n"); 19 | /* 执行SQL语句 */ 20 | res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 5"); 21 | 22 | if (res) 23 | { 24 | printf("SELECT error: %s\n", mysql_error(&my_connection)); 25 | } 26 | else 27 | { 28 | /* 将数据库中的数据一次性全部取出,该函数返回一个指向结果集结构的指针 */ 29 | res_ptr = mysql_store_result(&my_connection); 30 | if (res_ptr) 31 | { 32 | /* 使用mysql_num_rows语句得到数据库中记录的数目 */ 33 | printf("Retrieved %lu rows\n", (unsigned long)mysql_num_rows(res_ptr)); 34 | /* 一次从结果集中提取一行 */ 35 | while ((sqlrow = mysql_fetch_row(res_ptr))) 36 | { 37 | printf("Fetched data……\n"); 38 | } 39 | 40 | if (mysql_errno(&my_connection)) 41 | { 42 | fprintf(stderr, "Retrieved error: %s\n", mysql_error(&my_connection)); 43 | } 44 | /* 释放查询占用的内存资源,进行清理 */ 45 | mysql_free_result(res_ptr); 46 | } 47 | } 48 | mysql_close(&my_connection); 49 | } 50 | else 51 | { 52 | fprintf(stderr, "Connection failed\n"); 53 | if (mysql_errno(&my_connection)) 54 | { 55 | fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 56 | } 57 | } 58 | return EXIT_SUCCESS; 59 | } 60 | -------------------------------------------------------------------------------- /Chapter08/select2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/select2 -------------------------------------------------------------------------------- /Chapter08/select2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | MYSQL my_connection; 7 | MYSQL_RES *res_ptr; 8 | MYSQL_ROW sqlrow; 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | int res; 13 | 14 | mysql_init(&my_connection); 15 | /* 与数据库进行连接 */ 16 | if (mysql_real_connect(&my_connection, "localhost", "rick", "secret", "foo", 0, NULL, 0)) 17 | { 18 | printf("Connection success\n"); 19 | /* 执行SQL语句 */ 20 | res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 5"); 21 | 22 | if (res) 23 | { 24 | printf("SELECT error: %s\n", mysql_error(&my_connection)); 25 | } 26 | else 27 | { 28 | /* 将数据库中的数据一次性全部取出,该函数返回一个指向结果集结构的指针 */ 29 | res_ptr = mysql_use_result(&my_connection); 30 | if (res_ptr) 31 | { 32 | /* 当使用mysql_use_result来获取数据时,将无法使用mysql_num_rows语句得到数据库中记录的数目 */ 33 | /* 一次从结果集中提取一行 */ 34 | while ((sqlrow = mysql_fetch_row(res_ptr))) 35 | { 36 | printf("Fetched data……\n"); 37 | } 38 | 39 | if (mysql_errno(&my_connection)) 40 | { 41 | fprintf(stderr, "Retrieved error: %s\n", mysql_error(&my_connection)); 42 | } 43 | /* 释放查询占用的内存资源,进行清理 */ 44 | mysql_free_result(res_ptr); 45 | } 46 | } 47 | mysql_close(&my_connection); 48 | } 49 | else 50 | { 51 | fprintf(stderr, "Connection failed\n"); 52 | if (mysql_errno(&my_connection)) 53 | { 54 | fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 55 | } 56 | } 57 | return EXIT_SUCCESS; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /Chapter08/select3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/select3 -------------------------------------------------------------------------------- /Chapter08/select3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | MYSQL my_connection; 7 | MYSQL_RES *res_ptr; 8 | MYSQL_ROW sqlrow; 9 | 10 | void display_row(void); 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | int res; 15 | 16 | mysql_init(&my_connection); 17 | /* 与数据库进行连接 */ 18 | if (mysql_real_connect(&my_connection, "localhost", "rick", "secret", "foo", 0, NULL, 0)) 19 | { 20 | printf("Connection success\n"); 21 | /* 执行SQL语句 */ 22 | res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 5"); 23 | 24 | if (res) 25 | { 26 | printf("SELECT error: %s\n", mysql_error(&my_connection)); 27 | } 28 | else 29 | { 30 | /* 将数据库中的数据一次性全部取出,该函数返回一个指向结果集结构的指针 */ 31 | res_ptr = mysql_use_result(&my_connection); 32 | if (res_ptr) 33 | { 34 | /* 当使用mysql_use_result来获取数据时,将无法使用mysql_num_rows语句得到数据库中记录的数目 */ 35 | /* 一次从结果集中提取一行 */ 36 | while ((sqlrow = mysql_fetch_row(res_ptr))) 37 | { 38 | printf("Fetched data……\n"); 39 | display_row(); 40 | } 41 | 42 | if (mysql_errno(&my_connection)) 43 | { 44 | fprintf(stderr, "Retrieved error: %s\n", mysql_error(&my_connection)); 45 | } 46 | /* 释放查询占用的内存资源,进行清理 */ 47 | mysql_free_result(res_ptr); 48 | } 49 | } 50 | mysql_close(&my_connection); 51 | } 52 | else 53 | { 54 | fprintf(stderr, "Connection failed\n"); 55 | if (mysql_errno(&my_connection)) 56 | { 57 | fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 58 | } 59 | } 60 | return EXIT_SUCCESS; 61 | } 62 | 63 | 64 | void display_row() 65 | { 66 | unsigned int field_count; 67 | 68 | field_count = 0; 69 | while (field_count < mysql_field_count(&my_connection)) 70 | { 71 | printf("%s ", sqlrow[field_count]); 72 | field_count++; 73 | } 74 | printf("\n"); 75 | } 76 | -------------------------------------------------------------------------------- /Chapter08/select4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/select4 -------------------------------------------------------------------------------- /Chapter08/update1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter08/update1 -------------------------------------------------------------------------------- /Chapter08/update1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysql.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | /* 自定义一个连接句柄作为变量 */ 9 | MYSQL my_connection; 10 | 11 | int res; 12 | 13 | /* 使用非动态分配的连接结构 */ 14 | mysql_init(&my_connection); 15 | 16 | if (mysql_real_connect(&my_connection, "localhost", "rick", "secret", "foo", 0, NULL, 0)) 17 | { 18 | printf("Connection success\n"); 19 | res = mysql_query(&my_connection, "UPDATE children SET AGE = 4 WHERE fname = 'Ann'"); 20 | 21 | if (!res) 22 | { 23 | printf("Updated %lu rows\n", (unsigned long)mysql_affected_rows(&my_connection)); 24 | } 25 | else 26 | { 27 | fprintf(stderr, "Updated error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 28 | } 29 | mysql_close(&my_connection); 30 | } 31 | else 32 | { 33 | fprintf(stderr, "Connectin failed\n"); 34 | if (mysql_errno(&my_connection)) 35 | { 36 | fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&my_connection), mysql_error(&my_connection)); 37 | } 38 | } 39 | return EXIT_SUCCESS; 40 | } 41 | -------------------------------------------------------------------------------- /Chapter09/2.c: -------------------------------------------------------------------------------- 1 | #include "a.h" 2 | #include "b.h" 3 | 4 | void function_two() 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Chapter09/2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/2.o -------------------------------------------------------------------------------- /Chapter09/3.c: -------------------------------------------------------------------------------- 1 | #include "b.h" 2 | #include "c.h" 3 | 4 | void function_three() 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Chapter09/3.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/3.o -------------------------------------------------------------------------------- /Chapter09/Makefile1: -------------------------------------------------------------------------------- 1 | # This is a comment. 2 | myapp: main.o 2.o 3.o 3 | gcc -o myapp main.o 2.o 3.o 4 | 5 | main.o: main.c a.h 6 | gcc -c main.c 7 | 8 | 2.o: 2.c a.h b.h 9 | gcc -c 2.c 10 | 11 | 3.o: 3.c b.h c.h 12 | gcc -c 3.c 13 | -------------------------------------------------------------------------------- /Chapter09/Makefile2: -------------------------------------------------------------------------------- 1 | # 该makefile文件带有宏定义 2 | 3 | # 设定编译器 4 | CC = gcc 5 | 6 | # include文件的地址 7 | INCLUDE = 8 | 9 | # 开发时的编译选项 10 | CFLAGS = -g -Wall -ansi 11 | 12 | # 发行版的编译选项 13 | # CFLAGS = -O -Wall -ansi 14 | 15 | myapp: main.o 2.o 3.o 16 | $(CC) -o myapp main.o 2.o 3.o 17 | 18 | main.o: main.c a.h 19 | $(CC) -I$(INCLUDE) $(CFLAGS) -c main.c 20 | 21 | 2.o: 2.c a.h b.h 22 | $(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c 23 | 24 | 3.o: 3.c b.h c.h 25 | $(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c 26 | -------------------------------------------------------------------------------- /Chapter09/Makefile3: -------------------------------------------------------------------------------- 1 | all: myapp 2 | 3 | CC = gcc 4 | 5 | INSTDIR = /home/neuqsc/文档/Linux程序设计 6 | 7 | INCLUDE = 8 | 9 | CFLAGS = -g -Wall -ansi 10 | 11 | # 发行版的编译选项 12 | # CFLAGS = -O -wall -ansi 13 | 14 | myapp: main.o 2.o 3.o 15 | $(CC) -o myapp main.o 2.o 3.o 16 | 17 | main.o: main.c a.h 18 | $(CC) -I$(INCLUDE) $(CFLAGS) -c main.c 19 | 20 | 2.o: 2.c a.h b.h 21 | $(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c 22 | 23 | 3.o: 3.c b.h c.h 24 | $(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c 25 | 26 | 27 | # clean行的后面没有任何依赖关系,因此该目标总被认为是过时的,所以在执行make命令时,clean对应的语句总被执行 28 | # -的作用:让make命令忽略rm执行的所有错误 29 | clean: 30 | -rm main.o 2.o 3.o 31 | 32 | # @的作用是:让make在执行下面这些shell脚本前不显示这些命令本身 33 | # 必须在每行shell代码后面加上一个反斜杠,用于使所有的shell命令在同一个逻辑行上 34 | # 在每条shell语句的后面加上一个 && 表示与,只有在上一条命令执行成功的条件下,后一条命令才可以执行 35 | install: myapp 36 | @if [ -d $(INSTDIR) ];\ 37 | then \ 38 | cp myapp $(INSTDIR) && \ 39 | chmod a+x $(INSTDIR)/myapp && \ 40 | chmod og-w $(INSTDIR)/myapp && \ 41 | echo "Installed in $(INSTDIR)" ;\ 42 | else \ 43 | echo "Sorry, $(INSTDIR) does not exist"; false; \ 44 | fi 45 | -------------------------------------------------------------------------------- /Chapter09/Makefile5: -------------------------------------------------------------------------------- 1 | all: myapp 2 | 3 | CC = gcc 4 | 5 | INSTDIR = /home/neuqsc/文档/Linux程序设计/Chapter09 6 | 7 | INCLUDE = . 8 | 9 | CFLAGS = -g -Wall -ansi 10 | 11 | MYLIB = mylib.a 12 | 13 | myapp: main.o $(MYLIB) 14 | $(CC) -o myapp main.o $(MYLIB) 15 | 16 | $(MYLIB): $(MYLIB)(2.o) $(MYLIB)(3.o) 17 | main.o: main.c a.h 18 | 2.o: 2.c a.h b.h 19 | 3.o: 3.c b.h c.h 20 | 21 | clean: 22 | -rm main.o 2.o 3.o $(MYLIB) 23 | 24 | install: myapp 25 | @if [ -d $(INSTDIR) ]; \ 26 | then \ 27 | cp myapp $(INSTDIR) && \ 28 | chmod a+x $(INSTDIR)/myapp && \ 29 | chmod og-w $(INSTDIR)/myapp; \ 30 | echo "Installed in $(INSTDIR)"; \ 31 | else \ 32 | echo "Sorry, $(INSTDIR) does not exist"; \ 33 | fi 34 | -------------------------------------------------------------------------------- /Chapter09/Makefile6: -------------------------------------------------------------------------------- 1 | all: myapp 2 | 3 | CC = gcc 4 | 5 | INSTDIR = /home/neuqsc/文档/Linux程序设计/Chapter09 6 | 7 | INCLUDE = . 8 | 9 | CFLAGS = -g -Wall -ansi 10 | 11 | MYLIB = mylib.a 12 | 13 | myapp: main.o $(MYLIB) 14 | $(CC) -o myapp main.o $(MYLIB) 15 | 16 | $(MYLIB): $(MYLIB)(2.o) $(MYLIB)(3.o) 17 | main.o: main.c a.h 18 | 2.o: 2.c a.h b.h 19 | 3.o: 3.c b.h c.h 20 | 21 | clean: 22 | -rm main.o 2.o 3.o $(MYLIB) 23 | 24 | dist: myapp-1.0.tar.gz 25 | 26 | myapp-1.0.tar.gz: myapp myapp.1 27 | -rm -rf myapp-1.0 28 | mkdir myapp-1.0 29 | cp *.c *.h *.1 Makefile6 myapp-1.0 30 | tar zcvf $@ myapp-1.0 31 | -------------------------------------------------------------------------------- /Chapter09/RCS/important.c,v: -------------------------------------------------------------------------------- 1 | head 1.3; 2 | access; 3 | symbols; 4 | locks 5 | neuqsc:1.3; strict; 6 | comment @ * @; 7 | 8 | 9 | 1.3 10 | date 2018.02.13.10.07.07; author neuqsc; state Exp; 11 | branches; 12 | next 1.2; 13 | 14 | 1.2 15 | date 2018.02.13.09.53.30; author neuqsc; state Exp; 16 | branches; 17 | next 1.1; 18 | 19 | 1.1 20 | date 2018.02.13.09.49.57; author neuqsc; state Exp; 21 | branches; 22 | next ; 23 | 24 | 25 | desc 26 | @This is an important demonstration file 27 | @ 28 | 29 | 30 | 1.3 31 | log 32 | @Added $RCSfile$ and $Id$ strings 33 | @ 34 | text 35 | @/* 36 | This is an important file for managing this project. 37 | It implements the canonical "Hello World" program. 38 | */ 39 | 40 | #include 41 | #include 42 | 43 | /* 可以根据make命令的内置规则(推导规则)来简化甚至不用编写makefile文件 44 | 例如编译本程序可以使用如下命令: 45 | make foo 46 | 或者通过在命令行上修改宏来改变其默认行为: 47 | make CC=gcc CFLAGS="-g -Wall" foo 48 | */ 49 | 50 | static char *RCSinfo = "$Id$"; 51 | 52 | int main() 53 | { 54 | printf("Hello, World\n"); 55 | printf("This is an extra line added later\n"); 56 | printf("This file is under RCS control. Its ID is \n%s\n", RCSinfo); 57 | exit (EXIT_SUCCESS); 58 | } 59 | @ 60 | 61 | 62 | 1.2 63 | log 64 | @Added an extra line to be printed out. 65 | @ 66 | text 67 | @d16 2 68 | d22 1 69 | @ 70 | 71 | 72 | 1.1 73 | log 74 | @Initial revision 75 | @ 76 | text 77 | @d19 1 78 | @ 79 | -------------------------------------------------------------------------------- /Chapter09/a.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/a.h -------------------------------------------------------------------------------- /Chapter09/b.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/b.h -------------------------------------------------------------------------------- /Chapter09/c.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/c.h -------------------------------------------------------------------------------- /Chapter09/cvs-sp/Makefile: -------------------------------------------------------------------------------- 1 | hello: 2 | 3 | clean: 4 | -rm -f hello *~ 5 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("Hello World\n"); 7 | exit (EXIT_SUCCESS); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/CVS/Entries: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/cvs-sp/junk/neuqsc/CVS/Entries -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/CVS/Entries.Log: -------------------------------------------------------------------------------- 1 | A D/chap9-cvs//// 2 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/CVS/Entries.Static: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/cvs-sp/junk/neuqsc/CVS/Entries.Static -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/CVS/Repository: -------------------------------------------------------------------------------- 1 | neuqsc 2 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/CVS/Root: -------------------------------------------------------------------------------- 1 | /usr/local/repository 2 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/chap9-cvs/CVS/Entries: -------------------------------------------------------------------------------- 1 | /Makefile/1.1.1.1/Tue Feb 13 13:10:59 2018// 2 | /hello.c/1.2/Tue Feb 13 13:18:09 2018// 3 | D 4 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/chap9-cvs/CVS/Repository: -------------------------------------------------------------------------------- 1 | neuqsc/chap9-cvs 2 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/chap9-cvs/CVS/Root: -------------------------------------------------------------------------------- 1 | /usr/local/repository 2 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/chap9-cvs/Makefile: -------------------------------------------------------------------------------- 1 | hello: 2 | 3 | clean: 4 | -rm -f hello *~ 5 | -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/chap9-cvs/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/cvs-sp/junk/neuqsc/chap9-cvs/hello -------------------------------------------------------------------------------- /Chapter09/cvs-sp/junk/neuqsc/chap9-cvs/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("Hello World\n"); 7 | printf("Have a nice day\n"); 8 | exit (EXIT_SUCCESS); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter09/diffs: -------------------------------------------------------------------------------- 1 | 1c1 2 | < This is file one 3 | --- 4 | > This is file two 5 | 4c4,5 6 | < There is no line 4, this is line 5 7 | --- 8 | > line 4 9 | > line 5 10 | 5a7 11 | > a new line 8 12 | -------------------------------------------------------------------------------- /Chapter09/file1: -------------------------------------------------------------------------------- 1 | This is file one 2 | line 2 3 | line 3 4 | There is no line 4, this is line 5 5 | line 6 6 | -------------------------------------------------------------------------------- /Chapter09/file2: -------------------------------------------------------------------------------- 1 | This is file two 2 | line 2 3 | line 3 4 | line 4 5 | line 5 6 | line 6 7 | a new line 8 8 | -------------------------------------------------------------------------------- /Chapter09/foo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 可以根据make命令的内置规则(推导规则)来简化甚至不用编写makefile文件 5 | 例如编译本程序可以使用如下命令: 6 | make foo 7 | 或者通过在命令行上修改宏来改变其默认行为: 8 | make CC=gcc CFLAGS="-g -Wall" foo 9 | */ 10 | 11 | int main() 12 | { 13 | printf("Hello, World\n"); 14 | exit (EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter09/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "a.h" 3 | 4 | extern void function_two(); 5 | extern void function_three(); 6 | 7 | int main() 8 | { 9 | function_two(); 10 | function_three(); 11 | 12 | exit (EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter09/main.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/main.o -------------------------------------------------------------------------------- /Chapter09/myapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/myapp -------------------------------------------------------------------------------- /Chapter09/myapp-1.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/myapp-1.0.tar.gz -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/2.c: -------------------------------------------------------------------------------- 1 | #include "a.h" 2 | #include "b.h" 3 | 4 | void function_two() 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/3.c: -------------------------------------------------------------------------------- 1 | #include "b.h" 2 | #include "c.h" 3 | 4 | void function_three() 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/Makefile6: -------------------------------------------------------------------------------- 1 | all: myapp 2 | 3 | CC = gcc 4 | 5 | INSTDIR = /home/neuqsc/文档/Linux程序设计/Chapter09 6 | 7 | INCLUDE = . 8 | 9 | CFLAGS = -g -Wall -ansi 10 | 11 | MYLIB = mylib.a 12 | 13 | myapp: main.o $(MYLIB) 14 | $(CC) -o myapp main.o $(MYLIB) 15 | 16 | $(MYLIB): $(MYLIB)(2.o) $(MYLIB)(3.o) 17 | main.o: main.c a.h 18 | 2.o: 2.c a.h b.h 19 | 3.o: 3.c b.h c.h 20 | 21 | clean: 22 | -rm main.o 2.o 3.o $(MYLIB) 23 | 24 | dist: myapp-1.0.tar.gz 25 | 26 | myapp-1.0.tar.gz: myapp myapp.1 27 | -rm -rf myapp-1.0 28 | mkdir myapp-1.0 29 | cp *.c *.h *.1 Makefile6 myapp-1.0 30 | tar zcvf $@ myapp-1.0 31 | -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/a.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/myapp-1.0/a.h -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/b.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/myapp-1.0/b.h -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/c.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/myapp-1.0/c.h -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/foo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 可以根据make命令的内置规则(推导规则)来简化甚至不用编写makefile文件 5 | 例如编译本程序可以使用如下命令: 6 | make foo 7 | 或者通过在命令行上修改宏来改变其默认行为: 8 | make CC=gcc CFLAGS="-g -Wall" foo 9 | */ 10 | 11 | int main() 12 | { 13 | printf("Hello, World\n"); 14 | exit (EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "a.h" 3 | 4 | extern void function_two(); 5 | extern void function_three(); 6 | 7 | int main() 8 | { 9 | function_two(); 10 | function_three(); 11 | 12 | exit (EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter09/myapp-1.0/myapp.1: -------------------------------------------------------------------------------- 1 | .TH MYAPP 1 2 | 3 | .SH NAME 4 | Myapp \- A simple demonstration application that does very little. 5 | 6 | .SH SYNOPSIS 7 | .B myapp 8 | [\-option ...] 9 | 10 | .SH DESCRIPTION 11 | .PP 12 | \fImyapp\fP is a complete application that does nothing useful. 13 | 14 | .PP 15 | It was written for demonstration purposes. 16 | 17 | .SH OPTIONS 18 | .PP 19 | It doesn't have any, but lets pretend, to make this template complete: 20 | 21 | .TP 22 | .BI \-option 23 | If there was an option, it would not be -option. 24 | 25 | .SH RESOURCES 26 | .PP 27 | myapp uses almost no resources. 28 | 29 | .SH DIAGNOSTICS 30 | The program shouldn't output anything, so if you find it doing so there's 31 | probably something wrong. The return value is zero. 32 | 33 | .SH SEE ALSO 34 | The only other program we know with this little functionality is the 35 | ubiquitous hello world application. 36 | 37 | .SH COPYRIGHT 38 | myapp is Copyright (c) 2007 Wiley Publishing, Inc. 39 | 40 | This program is free software; you can redistribute it and/or modify 41 | it under the terms of the GNU General Public License as published by 42 | the Free Software Foundation; either version 2 of the License, or 43 | (at your option) any later version. 44 | 45 | This program is distributed in the hope that it will be useful, 46 | but WITHOUT ANY WARRANTY; without even the implied warranty of 47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48 | GNU General Public License for more details. 49 | 50 | You should have received a copy of the GNU General Public License 51 | along with this program; if not, write to the Free Software 52 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 53 | 54 | .SH BUGS 55 | There probably are some, but we don't know what they are yet. 56 | 57 | .SH AUTHORS 58 | Neil Matthew and Rick Stones 59 | 60 | -------------------------------------------------------------------------------- /Chapter09/myapp.1: -------------------------------------------------------------------------------- 1 | .TH MYAPP 1 2 | 3 | .SH NAME 4 | Myapp \- A simple demonstration application that does very little. 5 | 6 | .SH SYNOPSIS 7 | .B myapp 8 | [\-option ...] 9 | 10 | .SH DESCRIPTION 11 | .PP 12 | \fImyapp\fP is a complete application that does nothing useful. 13 | 14 | .PP 15 | It was written for demonstration purposes. 16 | 17 | .SH OPTIONS 18 | .PP 19 | It doesn't have any, but lets pretend, to make this template complete: 20 | 21 | .TP 22 | .BI \-option 23 | If there was an option, it would not be -option. 24 | 25 | .SH RESOURCES 26 | .PP 27 | myapp uses almost no resources. 28 | 29 | .SH DIAGNOSTICS 30 | The program shouldn't output anything, so if you find it doing so there's 31 | probably something wrong. The return value is zero. 32 | 33 | .SH SEE ALSO 34 | The only other program we know with this little functionality is the 35 | ubiquitous hello world application. 36 | 37 | .SH COPYRIGHT 38 | myapp is Copyright (c) 2007 Wiley Publishing, Inc. 39 | 40 | This program is free software; you can redistribute it and/or modify 41 | it under the terms of the GNU General Public License as published by 42 | the Free Software Foundation; either version 2 of the License, or 43 | (at your option) any later version. 44 | 45 | This program is distributed in the hope that it will be useful, 46 | but WITHOUT ANY WARRANTY; without even the implied warranty of 47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48 | GNU General Public License for more details. 49 | 50 | You should have received a copy of the GNU General Public License 51 | along with this program; if not, write to the Free Software 52 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 53 | 54 | .SH BUGS 55 | There probably are some, but we don't know what they are yet. 56 | 57 | .SH AUTHORS 58 | Neil Matthew and Rick Stones 59 | 60 | -------------------------------------------------------------------------------- /Chapter09/mylib.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter09/mylib.a -------------------------------------------------------------------------------- /Chapter10/assert: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/assert -------------------------------------------------------------------------------- /Chapter10/assert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | double my_sqrt(double x) 7 | { 8 | assert(x >= 0.0); 9 | return sqrt(x); 10 | } 11 | 12 | 13 | int main() 14 | { 15 | printf("sqrt +2 = %g\n", my_sqrt(2.0)); 16 | printf("sqrt -2 = %g\n", my_sqrt(-2.0)); 17 | exit (0); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter10/checker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/checker -------------------------------------------------------------------------------- /Chapter10/checker.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 使用valgrind来运行编译出的程序,可以检测内存泄露和数组访问出错的问题 */ 5 | 6 | /* 命令为: valgrind --leak-check=yes -v ./checker */ 7 | 8 | int main() 9 | { 10 | char *ptr = (char *)malloc(1024); 11 | char ch; 12 | 13 | /* 尝试未初始化就读取数据 */ 14 | ch = ptr[1024]; 15 | 16 | /* 在分配的内存块之后写数据 */ 17 | ptr[1024] = 0; 18 | 19 | ptr = 0; 20 | exit (0); 21 | } 22 | -------------------------------------------------------------------------------- /Chapter10/cinfo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/cinfo -------------------------------------------------------------------------------- /Chapter10/cinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 需要在编译该程序时,通过添加 -DDEBUG来启用调试 */ 5 | /* cc -o cinfo -DDEBUG cinfo.c */ 6 | 7 | int main() 8 | { 9 | #ifdef DEBUG 10 | printf("Compiled: "__DATE__" at "__TIME__"\n"); 11 | printf("This is line %d of file %s\n", __LINE__,__FILE__); 12 | #endif 13 | printf("hello world\n"); 14 | exit (0); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/debug0.c: -------------------------------------------------------------------------------- 1 | typedef struct 2 | { 3 | char *data; 4 | int key; 5 | } item; 6 | 7 | item array[] = 8 | { 9 | {"bill", 3}, 10 | {"neil", 4}, 11 | {"john", 2}, 12 | {"rick", 5}, 13 | {"alex", 1}, 14 | }; 15 | 16 | sort(a,n) 17 | item *a; 18 | { 19 | int i = 0, j = 0; 20 | int s; //用来指示是否已排序完成 21 | 22 | for (; i < n & s != 0; i++) 23 | { 24 | s = 0; 25 | for (j = 0;j < n;j++) 26 | { 27 | /* bug在这里,a[j+1]会超出数组的范围 */ 28 | if (a[j].key > a[j+1].key) 29 | { 30 | item t = a[j]; 31 | a[j] = a[j+1]; 32 | a[j+1] = t; 33 | s++; 34 | } 35 | } 36 | n--; 37 | } 38 | } 39 | 40 | main() 41 | { 42 | sort(array, 5); 43 | } 44 | -------------------------------------------------------------------------------- /Chapter10/debug1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/debug1 -------------------------------------------------------------------------------- /Chapter10/debug1.c: -------------------------------------------------------------------------------- 1 | typedef struct 2 | { 3 | char *data; 4 | int key; 5 | } item; 6 | 7 | item array[] = 8 | { 9 | {"bill", 3}, 10 | {"neil", 4}, 11 | {"john", 2}, 12 | {"rick", 5}, 13 | {"alex", 1}, 14 | }; 15 | 16 | sort(a,n) 17 | item *a; 18 | { 19 | int i = 0, j = 0; 20 | int s = 1; //用来指示是否已排序完成 21 | 22 | for (; i < n && s != 0; i++) 23 | { 24 | s = 0; 25 | for (j = 0;j < n;j++) 26 | { 27 | /* bug在这里,a[j+1]会超出数组的范围 */ 28 | if (a[j].key > a[j+1].key) 29 | { 30 | item t = a[j]; 31 | a[j] = a[j+1]; 32 | a[j+1] = t; 33 | s++; 34 | } 35 | } 36 | n--; 37 | } 38 | } 39 | 40 | main() 41 | { 42 | sort(array, 5); 43 | } 44 | -------------------------------------------------------------------------------- /Chapter10/debug2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/debug2 -------------------------------------------------------------------------------- /Chapter10/debug2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | char *data; 6 | int key; 7 | } item; 8 | 9 | item array[] = 10 | { 11 | {"bill", 3}, 12 | {"neil", 4}, 13 | {"john", 2}, 14 | {"rick", 5}, 15 | {"alex", 1}, 16 | }; 17 | 18 | sort(a,n) 19 | item *a; 20 | { 21 | int i = 0, j = 0; 22 | int s = 1; 23 | 24 | for (; i < n && s != 0; i++) 25 | { 26 | s = 0; 27 | for (j = 0;j < n;j++) 28 | { 29 | if (a[j].key > a[j+1].key) 30 | { 31 | item t = a[j]; 32 | a[j] = a[j+1]; 33 | a[j+1] = t; 34 | s++; 35 | } 36 | } 37 | n--; 38 | } 39 | } 40 | 41 | main() 42 | { 43 | int i; 44 | sort(array, 5); 45 | for (i = 0; i < 5;i++) 46 | { 47 | printf("array[%d] = {%s, %d}\n", i, array[i].data, array[i].key); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Chapter10/debug3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/debug3 -------------------------------------------------------------------------------- /Chapter10/debug3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | char data[4096]; 6 | int key; 7 | } item; 8 | 9 | item array[] = 10 | { 11 | {"bill", 3}, 12 | {"neil", 4}, 13 | {"john", 2}, 14 | {"rick", 5}, 15 | {"alex", 1}, 16 | }; 17 | 18 | sort(a,n) 19 | item *a; 20 | { 21 | int i = 0, j = 0; 22 | int s = 1; 23 | 24 | for (; i < n && s != 0; i++) 25 | { 26 | s = 0; 27 | for (j = 0; j < n; j++) 28 | { 29 | if (a[j].key > a[j+1].key) 30 | { 31 | item t = a[j]; 32 | a[j] = a[j+1]; 33 | a[j+1] = t; 34 | s++; 35 | } 36 | } 37 | n--; 38 | } 39 | } 40 | 41 | main() 42 | { 43 | int i; 44 | sort(array, 5); 45 | for (i = 0; i < 5;i++) 46 | { 47 | printf("array[%d] = {%s, %d}\n", i, array[i].data, array[i].key); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Chapter10/debug4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/debug4 -------------------------------------------------------------------------------- /Chapter10/debug4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | char data[4096]; 6 | int key; 7 | } item; 8 | 9 | item array[] = 10 | { 11 | {"bill", 3}, 12 | {"neil", 4}, 13 | {"john", 2}, 14 | {"rick", 5}, 15 | {"alex", 1}, 16 | }; 17 | 18 | sort(a,n) 19 | item *a; 20 | { 21 | int i = 0, j = 0; 22 | int s = 1; 23 | 24 | for (; i < n && s != 0; i++) 25 | { 26 | s = 0; 27 | for (j = 0; j < n-1; j++) 28 | { 29 | if (a[j].key > a[j+1].key) 30 | { 31 | item t = a[j]; 32 | a[j] = a[j+1]; 33 | a[j+1] = t; 34 | s++; 35 | } 36 | } 37 | n--; 38 | } 39 | } 40 | 41 | main() 42 | { 43 | int i; 44 | sort(array, 5); 45 | for (i = 0; i < 5;i++) 46 | { 47 | printf("array[%d] = {%s, %d}\n", i, array[i].data, array[i].key); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Chapter10/efence.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | /* 分配一个内存块 */ 7 | char *ptr = (char *)malloc(1024); 8 | ptr[0] = 0; 9 | 10 | /* 在上面分配的内存块后面写数据 */ 11 | ptr[1024] = 0; 12 | exit (0); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/gmon.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter10/gmon.out -------------------------------------------------------------------------------- /Chapter10/tmp: -------------------------------------------------------------------------------- 1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ 2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ 3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ 4 | !_TAG_PROGRAM_NAME Exuberant Ctags // 5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ 6 | !_TAG_PROGRAM_VERSION 5.9~svn20110310 // 7 | array debug4.c /^item array[] = $/;" v 8 | data debug4.c /^ char data[4096];$/;" m struct:__anon1 file: 9 | item debug4.c /^} item;$/;" t typeref:struct:__anon1 file: 10 | key debug4.c /^ int key;$/;" m struct:__anon1 file: 11 | main debug4.c /^main()$/;" f 12 | sort debug4.c /^sort(a,n)$/;" f 13 | -------------------------------------------------------------------------------- /Chapter11/alarm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/alarm -------------------------------------------------------------------------------- /Chapter11/alarm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int alarm_fired = 0; 8 | 9 | void ding(int sig) 10 | { 11 | alarm_fired = 1; 12 | } 13 | 14 | 15 | int main() 16 | { 17 | pid_t pid; 18 | printf("Alarm application starting\n"); 19 | 20 | pid = fork(); 21 | /* 子进程在等待5秒后发送一个SIGALRM信号给它的父进程 */ 22 | switch(pid) 23 | { 24 | case -1: 25 | perror("fork failed"); 26 | exit (1); 27 | case 0: 28 | sleep(5); 29 | kill(getppid(),SIGALRM); 30 | exit (0); 31 | } 32 | 33 | /* 父进程通过signal调用捕获SIGALRM信号 */ 34 | printf("waiting for alarm to go off\n"); 35 | /* 设置当捕获SIGALRM信号时,调用ding函数来处理该信号 */ 36 | (void) signal(SIGALRM, ding); 37 | /* 下面的sleep语句可也模拟“竟态条件”,即信号到来的时间出现在pause函数执行之前,则pause函数会一直等待下去 */ 38 | //sleep(2); 39 | /* 调用pause函数将父进程挂起,直到有一个信号出现为止 */ 40 | pause(); 41 | if (alarm_fired) 42 | { 43 | printf("Ding\n"); 44 | } 45 | printf("Done.\n"); 46 | exit (0); 47 | } 48 | -------------------------------------------------------------------------------- /Chapter11/ctrlc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/ctrlc -------------------------------------------------------------------------------- /Chapter11/ctrlc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 信号处理函数 */ 6 | void ouch(int sig) 7 | { 8 | printf("OUCH! - I got signal %d\n", sig); 9 | /* 截获一次中断信号之后,将恢复为默认的行为(即终止程序)*/ 10 | (void) signal(SIGINT, SIG_DFL); 11 | } 12 | 13 | 14 | /* 截获按下Ctrl+C组合键时产生的SIGINT信号 */ 15 | int main() 16 | { 17 | (void) signal(SIGINT, ouch); 18 | while (1) 19 | { 20 | printf("Hello World\n"); 21 | sleep(1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter11/ctrlc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/ctrlc2 -------------------------------------------------------------------------------- /Chapter11/ctrlc2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void ouch(int sig) 6 | { 7 | printf("OUCH! - I got signal %d\n", sig); 8 | } 9 | 10 | 11 | int main() 12 | { 13 | struct sigaction act; 14 | 15 | act.sa_handler = ouch; 16 | /* 将sa_mask(信号屏蔽字)初始化为0 */ 17 | sigemptyset(&act.sa_mask); 18 | act.sa_flags = 0; 19 | 20 | /* sigaction连续处理到来的SIGINT信号 */ 21 | sigaction(SIGINT, &act, 0); 22 | 23 | while (1) 24 | { 25 | printf("Hello World!\n"); 26 | sleep(1); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter11/execlp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/execlp -------------------------------------------------------------------------------- /Chapter11/execlp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 参数列表示例 */ 6 | char *const ps_argv[] = {"ps", "ax", 0}; 7 | 8 | /* 作为示例的环境 */ 9 | char *const ps_envp[] = {"PATH=/bin:/usr/bin", "TERM=console", 0}; 10 | 11 | /* exec系列函数示例 */ 12 | /* 在本程序中,我们选择execlp函数作为示范 */ 13 | //execl("/bin/ps", "ps", "ax", 0); 14 | //execlp("ps", "ps", "ax", 0); 15 | //execle("/bin/ps", "ps", "ax", 0, ps_envp); 16 | 17 | //execv("/bin/ps", ps_argv); 18 | //execvp("ps", ps_argv); 19 | //execve("/bin/ps", ps_argv, ps_envp); 20 | 21 | int main() 22 | { 23 | printf("Running ps with execlp\n"); 24 | execlp("ps", "ps", "ax", 0); 25 | printf("Done.\n"); 26 | exit (0); 27 | } 28 | -------------------------------------------------------------------------------- /Chapter11/file.txt: -------------------------------------------------------------------------------- 1 | this is the file, file.txt, it is all lower case. 2 | -------------------------------------------------------------------------------- /Chapter11/fork1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/fork1 -------------------------------------------------------------------------------- /Chapter11/fork1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | /* 在父进程中的fork调用返回的是新的子进程的PID 8 | 而子进程中的fork调用返回的是0 9 | 父子进程可以通过这一点来判断究竟谁是父进程,谁是子进程。 10 | */ 11 | 12 | int main() 13 | { 14 | pid_t pid; 15 | char *message; 16 | int n; 17 | 18 | printf("fork program starting\n"); 19 | pid = fork(); 20 | /* 在上一语句调用fork之后,程序被分为两个独立的进程 */ 21 | switch(pid) 22 | { 23 | case -1: 24 | perror("fork failed"); 25 | exit (1); 26 | case 0: 27 | message = "This is the child"; 28 | n = 5; 29 | break; 30 | default: 31 | message = "This is the parent"; 32 | n = 3; 33 | break; 34 | } 35 | 36 | for (; n > 0; n--) 37 | { 38 | puts(message); 39 | sleep(1); 40 | } 41 | exit (0); 42 | } 43 | -------------------------------------------------------------------------------- /Chapter11/fork2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/fork2 -------------------------------------------------------------------------------- /Chapter11/fork2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | /* 在父进程中的fork调用返回的是新的子进程的PID 8 | 而子进程中的fork调用返回的是0 9 | 父子进程可以通过这一点来判断究竟谁是父进程,谁是子进程。 10 | */ 11 | 12 | int main() 13 | { 14 | pid_t pid; 15 | char *message; 16 | int n; 17 | 18 | printf("fork program starting\n"); 19 | pid = fork(); 20 | /* 在上一语句调用fork之后,程序被分为两个独立的进程 */ 21 | switch(pid) 22 | { 23 | case -1: 24 | perror("fork failed"); 25 | exit (1); 26 | case 0: 27 | message = "This is the child"; 28 | n = 3; 29 | break; 30 | default: 31 | message = "This is the parent"; 32 | n = 5; 33 | break; 34 | } 35 | 36 | for (; n > 0; n--) 37 | { 38 | puts(message); 39 | sleep(1); 40 | } 41 | exit (0); 42 | } 43 | -------------------------------------------------------------------------------- /Chapter11/system1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/system1 -------------------------------------------------------------------------------- /Chapter11/system1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("Running ps with system\n"); 7 | /* system函数的作用是:把传进去的字符串参数作为命令,并运行之,等待该命令运行完成。*/ 8 | system("ps ax"); 9 | printf("Done\n"); 10 | exit (0); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter11/system2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/system2 -------------------------------------------------------------------------------- /Chapter11/system2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("Running ps with system\n"); 7 | /* system函数的作用是:把传进去的字符串参数作为命令,并运行之,等待该命令运行完成。*/ 8 | /* 在下面这条命令中,加上了&,则对system函数的调用将在shell命令结束后立刻返回 */ 9 | system("ps ax &"); 10 | printf("Done\n"); 11 | exit (0); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter11/upper: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/upper -------------------------------------------------------------------------------- /Chapter11/upper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int ch; 8 | while ((ch = getchar()) != EOF) 9 | { 10 | putchar(toupper(ch)); 11 | } 12 | exit (0); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter11/useupper: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/useupper -------------------------------------------------------------------------------- /Chapter11/useupper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | char *filename; 8 | if (argc != 2) 9 | { 10 | fprintf(stderr, "usage: useupper file\n"); 11 | exit (1); 12 | } 13 | filename = argv[1]; 14 | 15 | /* 用freopen函数先关闭标准输入,然后将文件流stdin与程序参数给定的文件名关联起来 */ 16 | if (!freopen(filename, "r", stdin)) 17 | { 18 | fprintf(stderr, "could not redirect stdin from file %s\n", filename); 19 | exit (2); 20 | } 21 | 22 | execl("./upper", "upper", 0); 23 | perror("could not exec ./upper"); 24 | exit (3); 25 | } 26 | -------------------------------------------------------------------------------- /Chapter11/wait: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter11/wait -------------------------------------------------------------------------------- /Chapter11/wait.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* wait函数的作用:暂停父进程直到它的子进程结束为止 8 | 该调用返回子进程的PID,它通常是已结束运行的子进程的PID 9 | */ 10 | 11 | /* 在父进程中的fork调用返回的是新的子进程的PID 12 | 而子进程中的fork调用返回的是0 13 | 父子进程可以通过这一点来判断究竟谁是父进程,谁是子进程。 14 | */ 15 | 16 | int main() 17 | { 18 | pid_t pid; 19 | char *message; 20 | int n; 21 | int exit_code; 22 | 23 | printf("fork program starting\n"); 24 | pid = fork(); 25 | /* 在上一语句调用fork之后,程序被分为两个独立的进程 */ 26 | switch(pid) 27 | { 28 | case -1: 29 | perror("fork failed"); 30 | exit (1); 31 | case 0: 32 | message = "This is the child"; 33 | n = 5; 34 | exit_code = 37; 35 | break; 36 | default: 37 | message = "This is the parent"; 38 | n = 3; 39 | exit_code = 0; 40 | break; 41 | } 42 | 43 | for (; n > 0; n--) 44 | { 45 | puts(message); 46 | sleep(1); 47 | } 48 | 49 | /* 下面这段代码由父进程执行 */ 50 | if (pid != 0) 51 | { 52 | int stat_val; 53 | pid_t child_pid; 54 | 55 | child_pid = wait(&stat_val); 56 | printf("Child has finished: PID = %d\n", child_pid); 57 | /* 如果子进程正常退出,则WIFEXITED(stat_val)就取一个非零值 */ 58 | if (WIFEXITED(stat_val)) 59 | { 60 | /* 如果WIFEXITED非零,则返回子进程的退出码 */ 61 | printf("Child exited with code %d\n", WEXITSTATUS(stat_val)); 62 | } 63 | else 64 | { 65 | printf("Child terminated abnormally\n"); 66 | } 67 | } 68 | exit (exit_code); 69 | } 70 | -------------------------------------------------------------------------------- /Chapter12/thread1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread1 -------------------------------------------------------------------------------- /Chapter12/thread1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | /* 编译该程序时,首先需要定义宏_REENTRANT,接下来必须链接正确的线程库。 9 | 本系统默认使用的是NPTL线程库,则编译时无需加上-I 和 -L选项 10 | 编译命令为: 11 | cc -D_REENTRANT thread1.c -o thread1 -lpthread 12 | 完整的命令为: 13 | cc -D_REENTRANT -I/usr/include/nptl thread1.c -o thread1 -L/usr/lib/nptl -lpthread 14 | */ 15 | 16 | void *thread_function(void *arg); 17 | 18 | char message[] = "Hello World"; 19 | 20 | int main() 21 | { 22 | int res; 23 | pthread_t a_thread; 24 | void *thread_result; 25 | 26 | /* 创建一个线程: 27 | 第一个参数:指向pthread_t类型数据的指针,指向的变量内容被写入一个标识符中,用来引用新线程 28 | 第二个参数:设置线程的属性,一般设置为NULL 29 | 第三个参数:新线程启动执行的函数指针 30 | 第四个参数:传递给上面函数的参数 31 | 注意:对于新线程来说,其将在启动函数处开始运行 32 | */ 33 | res = pthread_create(&a_thread, NULL, thread_function, (void *)message); 34 | if (res != 0) 35 | { 36 | perror("Thread creation failed"); 37 | exit (EXIT_FAILURE); 38 | } 39 | 40 | printf("Waiting for thread to finish……\n"); 41 | 42 | /* 等价于进程中用来收集子进程信息的wait函数 43 | 该函数将等到它所指定的线程终止后才返回 44 | 第一个参数:指定将要等待的线程,该线程通过pthread_create返回的标识符来指定 45 | 第二个参数:是一个指针,指向另一个指针,而后者指向线程的返回值 46 | */ 47 | res = pthread_join(a_thread, &thread_result); 48 | if (res != 0) 49 | { 50 | perror("Thread join failed"); 51 | exit (EXIT_FAILURE); 52 | } 53 | 54 | printf("Thread joined, it returned %s\n", (char *)thread_result); 55 | printf("Message is now %s\n", message); 56 | exit (EXIT_SUCCESS); 57 | } 58 | 59 | 60 | /* 线程的启动函数 */ 61 | void *thread_function(void *arg) 62 | { 63 | printf("thread_function is running. Argument was %s\n", (char *)arg); 64 | sleep(3); 65 | strcpy(message, "Bye!"); 66 | /* 该函数的作用是:终止调用它的线程并返回一个指向某个对象的指针 */ 67 | pthread_exit("Thank you for the CPU time"); 68 | } 69 | -------------------------------------------------------------------------------- /Chapter12/thread2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread2 -------------------------------------------------------------------------------- /Chapter12/thread2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 在本程序中,我们使用轮询技术,来验证两个线程的执行是同时进行的 */ 8 | 9 | /* 进程的所有线程,除局部变量外,所有其他变量都将在一个进程中的所有线程之间共享 10 | */ 11 | 12 | /* 编译该程序时,首先需要定义宏_REENTRANT,接下来必须链接正确的线程库。 13 | 本系统默认使用的是NPTL线程库,则编译时无需加上-I 和 -L选项 14 | 编译命令为: 15 | cc -D_REENTRANT thread2.c -o thread2 -lpthread 16 | 完整的命令为: 17 | cc -D_REENTRANT -I/usr/include/nptl thread2.c -o thread2 -L/usr/lib/nptl -lpthread 18 | */ 19 | 20 | void *thread_function(void *arg); 21 | int run_now = 1; 22 | 23 | int main() 24 | { 25 | int res; 26 | int print_count1 = 0; 27 | pthread_t a_thread; 28 | void *thread_result; 29 | 30 | /* 创建一个线程: 31 | 第一个参数:指向pthread_t类型数据的指针,指向的变量内容被写入一个标识符中,用来引用新线程 32 | 第二个参数:设置线程的属性,一般设置为NULL 33 | 第三个参数:新线程启动执行的函数指针 34 | 第四个参数:传递给上面函数的参数 35 | 注意:对于新线程来说,其将在启动函数处开始运行 36 | */ 37 | res = pthread_create(&a_thread, NULL, thread_function, (void *)message); 38 | if (res != 0) 39 | { 40 | perror("Thread creation failed"); 41 | exit (EXIT_FAILURE); 42 | } 43 | 44 | /* 忙等待 */ 45 | /* 变量run_now被两个线程共享,当其为1时,main线程输出1,并将其改为2;则新线程检测到该变量为2时,则输出2,并将其改为1 */ 46 | while (print_count1++ < 20) 47 | { 48 | if (run_now == 1) 49 | { 50 | printf("1"); 51 | run_now = 2; 52 | } 53 | else 54 | { 55 | sleep(1); 56 | } 57 | } 58 | 59 | printf("\nWaiting for thread to finish……\n"); 60 | 61 | /* 等价于进程中用来收集子进程信息的wait函数 62 | 该函数将等到它所指定的线程终止后才返回 63 | 第一个参数:指定将要等待的线程,该线程通过pthread_create返回的标识符来指定 64 | 第二个参数:是一个指针,指向另一个指针,而后者指向线程的返回值 65 | */ 66 | res = pthread_join(a_thread, &thread_result); 67 | if (res != 0) 68 | { 69 | perror("Thread join failed"); 70 | exit (EXIT_FAILURE); 71 | } 72 | 73 | printf("Thread joined"); 74 | exit (EXIT_SUCCESS); 75 | } 76 | 77 | 78 | /* 线程的启动函数 */ 79 | void *thread_function(void *arg) 80 | { 81 | int print_count2 = 0; 82 | 83 | while (print_count2++ < 20) 84 | { 85 | if (run_now == 2) 86 | { 87 | printf("2"); 88 | run_now = 1; 89 | } 90 | else 91 | { 92 | sleep(1); 93 | } 94 | } 95 | 96 | sleep(3); 97 | } 98 | -------------------------------------------------------------------------------- /Chapter12/thread3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread3 -------------------------------------------------------------------------------- /Chapter12/thread3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 程序一开始,将二进制信号量初始化为0,则新线程中的sem_wait函数将会阻塞 9 | 在主线程中,等待用户从键盘输入,并通过sem_post函数将信号量加1,则新线 10 | 程中的sem_wait函数返回并开始执行,在统计完字符个数之后,它再次调用sem_wait 11 | (信号量变为0)并再次被阻塞,直到主线程再次调用sem_post增加信号量的值 12 | */ 13 | 14 | void *thread_function(void *arg); 15 | /* 创建二进制信号量 */ 16 | sem_t bin_sem; 17 | 18 | #define WORK_SIZE 1024 19 | char work_area[WORK_SIZE]; 20 | 21 | int main() 22 | { 23 | int res; 24 | pthread_t a_thread; 25 | void *thread_result; 26 | 27 | /* 将二进制信号量初始化为0,并且第二个参数为0表示是当前进程的局部信号量 */ 28 | res = sem_init(&bin_sem, 0, 0); 29 | if (res != 0) 30 | { 31 | perror("Semaphore initialization failed"); 32 | exit (EXIT_FAILURE); 33 | } 34 | 35 | /* 创建新线程 */ 36 | res = pthread_create(&a_thread, NULL, thread_function, NULL); 37 | if (res != 0) 38 | { 39 | perror("Thread creation failed"); 40 | exit (EXIT_FAILURE); 41 | } 42 | 43 | /* 向工作区中输入一些文本 */ 44 | printf("Input some text. Enter 'end' to finish\n"); 45 | /* 当没有读入end时,则继续读取文本 */ 46 | /* strncmp:在work_area的前3个字节里搜寻是否存在end字符串 */ 47 | while (strncmp("end", work_area, 3) != 0) 48 | { 49 | fgets(work_area, WORK_SIZE, stdin); 50 | /* 调用sem_post增加信号量的值 */ 51 | sem_post(&bin_sem); 52 | } 53 | 54 | printf("\nWaiting for thread to finish……\n"); 55 | res = pthread_join(a_thread, &thread_result); 56 | 57 | if (res != 0) 58 | { 59 | perror("Thread join failed"); 60 | exit (EXIT_FAILURE); 61 | } 62 | 63 | 64 | printf("Thread joined\n"); 65 | sem_destroy(&bin_sem); 66 | exit (EXIT_SUCCESS); 67 | } 68 | 69 | 70 | void *thread_function(void *arg) 71 | { 72 | /* 在新线程中,等待信号量,统计来自输入的字符个数 */ 73 | sem_wait(&bin_sem); 74 | while (strncmp("end", work_area, 3) != 0) 75 | { 76 | printf("You input %d characters\n", strlen(work_area) - 1); 77 | sem_wait(&bin_sem); 78 | } 79 | pthread_exit(NULL); 80 | } 81 | -------------------------------------------------------------------------------- /Chapter12/thread4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread4 -------------------------------------------------------------------------------- /Chapter12/thread4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void *thread_function(void *arg); 9 | /* 创建互斥量,用来保护工作区和变量time_to_exit */ 10 | pthread_mutex_t work_mutex; 11 | 12 | #define WORK_SIZE 1024 13 | char work_area[WORK_SIZE]; 14 | int time_to_exit = 0; 15 | 16 | int main() 17 | { 18 | int res; 19 | pthread_t a_thread; 20 | void *thread_result; 21 | /* 初始化互斥量 */ 22 | res = pthread_mutex_init(&work_mutex, NULL); 23 | if (res != 0) 24 | { 25 | perror("Mutex initialization failed"); 26 | exit (EXIT_FAILURE); 27 | } 28 | 29 | res = pthread_create(&a_thread, NULL, thread_function, NULL); 30 | if (res != 0) 31 | { 32 | perror("Thread creation failed"); 33 | exit (EXIT_FAILURE); 34 | } 35 | 36 | /* 主线程里先对工作区进行加锁 */ 37 | pthread_mutex_lock(&work_mutex); 38 | printf("Input some text. Enter 'end' to finish\n"); 39 | while (!time_to_exit) 40 | { 41 | /* 输入文本并解锁,让新线程统计字符数目 */ 42 | fgets(work_area, WORK_SIZE, stdin); 43 | pthread_mutex_unlock(&work_mutex); 44 | /* 判断新线程是否统计完(通过判断work_ared[0]是否为NULL)*/ 45 | while (1) 46 | { 47 | pthread_mutex_lock(&work_mutex); 48 | /* 如果还未统计完,则保持解锁使新线程继续统计 */ 49 | if (work_area[0] != '\0') 50 | { 51 | pthread_mutex_unlock(&work_mutex); 52 | sleep(1); 53 | } 54 | else 55 | { 56 | break; 57 | } 58 | } 59 | } 60 | 61 | /* 在退出程序前,对工作区进行解锁 */ 62 | pthread_mutex_unlock(&work_mutex); 63 | printf("\nWaiting for thread to finish……\n"); 64 | res = pthread_join(a_thread, &thread_result); 65 | if (res != 0) 66 | { 67 | perror("Thread join failed"); 68 | exit (EXIT_FAILURE); 69 | } 70 | 71 | printf("Thread joined\n"); 72 | pthread_mutex_destroy(&work_mutex); 73 | exit (EXIT_SUCCESS); 74 | } 75 | 76 | 77 | void *thread_function(void *arg) 78 | { 79 | sleep(1); 80 | /* 对工作区进行加锁,并开始统计 */ 81 | pthread_mutex_lock(&work_mutex); 82 | while (strncmp("end", work_area, 3) != 0) 83 | { 84 | printf("You input %d characters\n", strlen(work_area) - 1); 85 | /* 统计完成之后,将work_area[0]设为NULL,向主线程表明统计完成 */ 86 | work_area[0] = '\0'; 87 | /* 解锁,使主线程能够继续读取输入 */ 88 | pthread_mutex_unlock(&work_mutex); 89 | sleep(1); 90 | /* 周期性地尝试加锁,如果成功,则检查主线程是否又读入了字符;如果没有,则解锁互斥量继续等待 */ 91 | pthread_mutex_lock(&work_mutex); 92 | while (work_area[0] == '\0') 93 | { 94 | pthread_mutex_unlock(&work_mutex); 95 | sleep(1); 96 | pthread_mutex_lock(&work_mutex); 97 | } 98 | } 99 | /* 做退出程序前的准备 */ 100 | time_to_exit = 1; 101 | work_area[0] = '\0'; 102 | pthread_mutex_unlock(&work_mutex); 103 | pthread_exit(0); 104 | } 105 | -------------------------------------------------------------------------------- /Chapter12/thread5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread5 -------------------------------------------------------------------------------- /Chapter12/thread5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 在本程序中,创建新线程并设置其属性为脱离状态,则可以允许第二个线程独立的完成工作,而无需原先的线程等待它 */ 7 | 8 | void *thread_function(void *arg); 9 | 10 | char message[] = "Hello World"; 11 | 12 | /* 作为新线程是否结束的标志 */ 13 | int thread_finished = 0; 14 | 15 | int main() 16 | { 17 | int res; 18 | pthread_t a_thread; 19 | 20 | pthread_attr_t thread_attr; 21 | 22 | /* 创建一个线程属性,并对其进行初始化 */ 23 | res = pthread_attr_init(&thread_attr); 24 | if (res != 0) 25 | { 26 | perror("Attribute creation failed"); 27 | exit (EXIT_FAILURE); 28 | } 29 | 30 | /* 将线程属性设置为脱离状态 */ 31 | res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); 32 | if (res != 0) 33 | { 34 | perror("Setting detached attribute failed"); 35 | exit (EXIT_FAILURE); 36 | } 37 | 38 | /* 在创建新线程时,要指明属性 */ 39 | res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message); 40 | if (res != 0) 41 | { 42 | perror("Thread creation failed"); 43 | exit (EXIT_FAILURE); 44 | } 45 | 46 | /* 属性用完后,对其进行回收 */ 47 | (void)pthread_attr_destroy(&thread_attr); 48 | 49 | /* 等待新线程结束 */ 50 | while (!thread_finished) 51 | { 52 | printf("Waiting for thread to say it's finished……\n"); 53 | sleep(1); 54 | } 55 | 56 | printf("Other thread finished, bye!\n"); 57 | exit (EXIT_SUCCESS); 58 | } 59 | 60 | 61 | void *thread_function(void *arg) 62 | { 63 | printf("thread_function is running. Argument was %s\n", (char *)arg); 64 | sleep(4); 65 | printf("Second thread setting finished flag, and exiting now\n"); 66 | /* 对新线程结束标志赋值,该变量由两个线程共享 */ 67 | thread_finished = 1; 68 | pthread_exit(NULL); 69 | } 70 | -------------------------------------------------------------------------------- /Chapter12/thread6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread6 -------------------------------------------------------------------------------- /Chapter12/thread6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 在本程序中,创建新线程并设置其属性为脱离状态,则可以允许第二个线程独立的完成工作,而无需原先的线程等待它 */ 7 | 8 | void *thread_function(void *arg); 9 | 10 | char message[] = "Hello World"; 11 | 12 | int max_priority; 13 | int min_priority; 14 | struct sched_param scheduling_value; 15 | 16 | /* 作为新线程是否结束的标志 */ 17 | int thread_finished = 0; 18 | 19 | int main() 20 | { 21 | int res; 22 | pthread_t a_thread; 23 | 24 | pthread_attr_t thread_attr; 25 | 26 | /* 创建一个线程属性,并对其进行初始化 */ 27 | res = pthread_attr_init(&thread_attr); 28 | if (res != 0) 29 | { 30 | perror("Attribute creation failed"); 31 | exit (EXIT_FAILURE); 32 | } 33 | 34 | /* 将线程属性设置为脱离状态 */ 35 | res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); 36 | if (res != 0) 37 | { 38 | perror("Setting detached attribute failed"); 39 | exit (EXIT_FAILURE); 40 | } 41 | 42 | /* 设置调度策略 */ 43 | res = pthread_attr_setschedpolicy(&thread_attr, SCHED_OTHER); 44 | if (res != 0) 45 | { 46 | perror("Setting scheduling policy failed"); 47 | exit (EXIT_FAILURE); 48 | } 49 | 50 | /* 在创建新线程时,要指明属性 */ 51 | res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message); 52 | if (res != 0) 53 | { 54 | perror("Thread creation failed"); 55 | exit (EXIT_FAILURE); 56 | } 57 | 58 | /* 查找允许的优先级范围 */ 59 | max_priority = sched_get_priority_max(SCHED_OTHER); 60 | min_priority = sched_get_priority_min(SCHED_OTHER); 61 | 62 | /* 设置优先级 */ 63 | scheduling_value.sched_priority = min_priority; 64 | res = pthread_attr_setschedparam(&thread_attr, &scheduling_value); 65 | if (res != 0) 66 | { 67 | perror("Setting schedpolicy failed"); 68 | exit (EXIT_FAILURE); 69 | } 70 | 71 | 72 | /* 属性用完后,对其进行回收 */ 73 | (void)pthread_attr_destroy(&thread_attr); 74 | 75 | /* 等待新线程结束 */ 76 | while (!thread_finished) 77 | { 78 | printf("Waiting for thread to say it's finished……\n"); 79 | sleep(1); 80 | } 81 | 82 | printf("Other thread finished, bye!\n"); 83 | exit (EXIT_SUCCESS); 84 | } 85 | 86 | 87 | void *thread_function(void *arg) 88 | { 89 | printf("thread_function is running. Argument was %s\n", (char *)arg); 90 | sleep(4); 91 | printf("Second thread setting finished flag, and exiting now\n"); 92 | /* 对新线程结束标志赋值,该变量由两个线程共享 */ 93 | thread_finished = 1; 94 | pthread_exit(NULL); 95 | } 96 | -------------------------------------------------------------------------------- /Chapter12/thread7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread7 -------------------------------------------------------------------------------- /Chapter12/thread7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *thread_function(void *arg); 7 | 8 | int main() 9 | { 10 | int res; 11 | pthread_t a_thread; 12 | void *thread_result; 13 | 14 | res = pthread_create(&a_thread, NULL, thread_function, NULL); 15 | if (res != 0) 16 | { 17 | perror("Thread creation failed"); 18 | exit (EXIT_FAILURE); 19 | } 20 | 21 | /* 主线程停止3秒后发送取消请求 */ 22 | sleep(3); 23 | printf("Canceling thread……\n"); 24 | res = pthread_cancel(a_thread); 25 | if (res != 0) 26 | { 27 | perror("Thread cancelation failed"); 28 | exit (EXIT_FAILURE); 29 | } 30 | 31 | printf("Waiting for thread to finish……\n"); 32 | res = pthread_join(a_thread, &thread_result); 33 | if (res != 0) 34 | { 35 | perror("Thread join failed"); 36 | exit (EXIT_FAILURE); 37 | } 38 | exit (EXIT_SUCCESS); 39 | } 40 | 41 | 42 | void *thread_function(void *arg) 43 | { 44 | int i, res; 45 | /* 设置自己的取消状态,--ENABLE 可以接受取消请求 */ 46 | res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 47 | if (res != 0) 48 | { 49 | perror("Thread pthread_setcancelstate failed"); 50 | exit (EXIT_FAILURE); 51 | } 52 | 53 | /* 当取消状态设置好之后,线程进入第二个控制层次,设置取消类型 */ 54 | /* 有两行类型: 55 | ① PTHREAD_CANCEL_ASYNCHRONOUS,使得在接收到取消请求后立即采取行动 56 | ② PTHREAD_CANCEL_DEFERRED,即延迟取消,使得在接收到取消请求后,一直等待直到线程执行了某些特定的函数 57 | */ 58 | res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); 59 | if (res != 0) 60 | { 61 | perror("Thread pthread_setcanceltype failed"); 62 | exit (EXIT_FAILURE); 63 | } 64 | 65 | printf("thread_function is running\n"); 66 | for (i = 0; i < 10;i++) 67 | { 68 | printf("Thread is still running (%d)……\n", i); 69 | sleep(1); 70 | } 71 | 72 | pthread_exit(0); 73 | } 74 | -------------------------------------------------------------------------------- /Chapter12/thread8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread8 -------------------------------------------------------------------------------- /Chapter12/thread8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define NUM_THREADS 6 7 | 8 | void *thread_function(void *arg); 9 | 10 | /* 修复thread8.c中的一些BUG */ 11 | 12 | int main() 13 | { 14 | int res; 15 | pthread_t a_thread[NUM_THREADS]; 16 | void *thread_result; 17 | int lots_of_threads; 18 | 19 | /* 通过循环,创建多个线程 */ 20 | for (lots_of_threads = 0; lots_of_threads < NUM_THREADS;lots_of_threads++) 21 | { 22 | res = pthread_create(&(a_thread[lots_of_threads]), NULL, thread_function, (void *)&lots_of_threads); 23 | if (res != 0) 24 | { 25 | perror("Thread creation failed"); 26 | exit (EXIT_FAILURE); 27 | } 28 | sleep(1); 29 | } 30 | 31 | printf("Waiting for threads to finish……\n"); 32 | 33 | /* 以和创建线程相反的顺序同步线程 */ 34 | for (lots_of_threads = NUM_THREADS - 1;lots_of_threads >= 0;lots_of_threads--) 35 | { 36 | res = pthread_join(a_thread[lots_of_threads], &thread_result); 37 | if (res == 0) 38 | { 39 | printf("Picked up a thread\n"); 40 | } 41 | else 42 | { 43 | perror("pthread_join failed"); 44 | } 45 | } 46 | printf("All done\n"); 47 | exit (EXIT_SUCCESS); 48 | } 49 | 50 | 51 | void *thread_function(void *arg) 52 | { 53 | int my_number = *(int *)arg; 54 | int rand_num; 55 | 56 | printf("thread_function is running. Argument was %d\n",my_number); 57 | 58 | /* 每个线程等待随机时间后退出 */ 59 | rand_num = 1 + (int)(9.0 * rand() / (RAND_MAX + 1.0)); 60 | sleep(rand_num); 61 | printf("Bye from %d\n", my_number); 62 | pthread_exit (NULL); 63 | } 64 | -------------------------------------------------------------------------------- /Chapter12/thread8a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter12/thread8a -------------------------------------------------------------------------------- /Chapter12/thread8a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define NUM_THREADS 6 7 | 8 | void *thread_function(void *arg); 9 | 10 | /* 修复thread8.c中的一些BUG */ 11 | 12 | int main() 13 | { 14 | int res; 15 | pthread_t a_thread[NUM_THREADS]; 16 | void *thread_result; 17 | int lots_of_threads; 18 | 19 | /* 通过循环,创建多个线程 */ 20 | for (lots_of_threads = 0; lots_of_threads < NUM_THREADS;lots_of_threads++) 21 | { 22 | res = pthread_create(&(a_thread[lots_of_threads]), NULL, thread_function, (void *)lots_of_threads); 23 | if (res != 0) 24 | { 25 | perror("Thread creation failed"); 26 | exit (EXIT_FAILURE); 27 | } 28 | sleep(1); 29 | } 30 | 31 | printf("Waiting for threads to finish……\n"); 32 | 33 | /* 以和创建线程相反的顺序同步线程 */ 34 | for (lots_of_threads = NUM_THREADS - 1;lots_of_threads >= 0;lots_of_threads--) 35 | { 36 | res = pthread_join(a_thread[lots_of_threads], &thread_result); 37 | if (res == 0) 38 | { 39 | printf("Picked up a thread\n"); 40 | } 41 | else 42 | { 43 | perror("pthread_join failed"); 44 | } 45 | } 46 | printf("All done\n"); 47 | exit (EXIT_SUCCESS); 48 | } 49 | 50 | 51 | void *thread_function(void *arg) 52 | { 53 | int my_number = (int)arg; 54 | int rand_num; 55 | 56 | printf("thread_function is running. Argument was %d\n",my_number); 57 | 58 | /* 每个线程等待随机时间后退出 */ 59 | rand_num = 1 + (int)(9.0 * rand() / (RAND_MAX + 1.0)); 60 | sleep(rand_num); 61 | printf("Bye from %d\n", my_number); 62 | pthread_exit (NULL); 63 | } 64 | -------------------------------------------------------------------------------- /Chapter13/client: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/client -------------------------------------------------------------------------------- /Chapter13/client.c: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | #include 3 | 4 | int main() 5 | { 6 | int server_fifo_fd, client_fifo_fd; 7 | struct data_to_pass_st my_data; 8 | int times_to_send; 9 | char client_fifo[256]; 10 | 11 | /* 以只写的阻塞模式打开服务器管道的文件描述符 */ 12 | server_fifo_fd = open(SERVER_FIFO_NAME, O_WRONLY); 13 | if (server_fifo_fd == -1) 14 | { 15 | fprintf(stderr, "Sorry, no server\n"); 16 | exit (EXIT_FAILURE); 17 | } 18 | 19 | /* 客户端程序获取自己的PID */ 20 | my_data.client_pid = getpid(); 21 | /* 将CLIENT_FIFO_NAME和client_pid结合起来 */ 22 | sprintf(client_fifo, CLIENT_FIFO_NAME, my_data.client_pid); 23 | if (mkfifo(client_fifo, 0777) == -1) 24 | { 25 | fprintf(stderr, "Sorry, can't make %s\n", client_fifo); 26 | exit (EXIT_FAILURE); 27 | } 28 | 29 | /* 在每次循环中,客户将数据发送给服务器,然后打开客户FIFO并读回数据 */ 30 | for (times_to_send = 0;times_to_send < 5;times_to_send++) 31 | { 32 | /* 通过sprintf组成一个包含客户pid的字符串,然后发送 */ 33 | sprintf(my_data.some_data, "Hello from %d", my_data.client_pid); 34 | /* 通过printf在终端上显示 某个PID发送了某个字符串 */ 35 | printf("%d sent %s, ", my_data.client_pid, my_data.some_data); 36 | /* 通过write函数,向服务器管道文件描述符写字符串 */ 37 | write(server_fifo_fd, &my_data, sizeof(my_data)); 38 | /* 打开客户管道 */ 39 | client_fifo_fd = open(client_fifo, O_RDONLY); 40 | if (client_fifo_fd != -1) 41 | { 42 | /* 通过客户管道文件描述符读取数据 */ 43 | if (read(client_fifo_fd, &my_data, sizeof(my_data)) > 0) 44 | { 45 | printf("received: %s\n", my_data.some_data); 46 | } 47 | close(client_fifo_fd); 48 | } 49 | } 50 | /* 关闭服务器管道,删除客户FIFO文件,并退出 */ 51 | close(server_fifo_fd); 52 | unlink(client_fifo); 53 | exit (EXIT_SUCCESS); 54 | } 55 | -------------------------------------------------------------------------------- /Chapter13/client.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define SERVER_FIFO_NAME "/tmp/serv_fifo" 11 | #define CLIENT_FIFO_NAME "/tmp/cli_%d_fifo" 12 | 13 | #define BUFFER_SIZE 20 14 | 15 | struct data_to_pass_st 16 | { 17 | pid_t client_pid; 18 | char some_data[BUFFER_SIZE - 1]; 19 | }; 20 | -------------------------------------------------------------------------------- /Chapter13/fifo1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/fifo1 -------------------------------------------------------------------------------- /Chapter13/fifo1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 使用mkfifo函数创建命名管道,用于在不相关的进程之间交换数据 */ 8 | /* 命名管道(named pipe):一种特殊类型的文件,它在文件系统中以文件名的形式存在,但其行为与没有名字的管道类似 */ 9 | int main() 10 | { 11 | int res = mkfifo("/tmp/my_fifo", 0777); 12 | if (res == 0) 13 | { 14 | printf("FIFO created\n"); 15 | } 16 | exit (EXIT_SUCCESS); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter13/fifo2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/fifo2 -------------------------------------------------------------------------------- /Chapter13/fifo2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define FIFO_NAME "/tmp/my_fifo" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int res; 14 | int open_mode = 0; 15 | int i; 16 | 17 | if (argc < 2) 18 | { 19 | fprintf(stderr, "Usage: %s \n", *argv); 20 | exit (EXIT_FAILURE); 21 | } 22 | 23 | /* 根据命令行参数来设置open_mode的值 */ 24 | for (i = 1;i < argc;i++) 25 | { 26 | if (strncmp(*++argv, "O_RDONLY", 8) == 0) 27 | { 28 | open_mode |= O_RDONLY; 29 | } 30 | if (strncmp(*argv, "O_WRONLY", 8) == 0) 31 | { 32 | open_mode |= O_WRONLY; 33 | } 34 | if (strncmp(*argv, "O_NONBLOCK", 10) == 0) 35 | { 36 | open_mode |= O_NONBLOCK; 37 | } 38 | } 39 | 40 | /* 检查FIFO文件是否存在,否则就创建它 */ 41 | if (access(FIFO_NAME, F_OK) == -1) 42 | { 43 | res = mkfifo(FIFO_NAME, 0777); 44 | if (res != 0) 45 | { 46 | fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); 47 | exit (EXIT_FAILURE); 48 | } 49 | } 50 | 51 | /* 打开FIFO文件,并输出相应的信息 */ 52 | printf("Process %d opening FIFO\n", getpid()); 53 | res = open(FIFO_NAME, open_mode); 54 | printf("Process %d result %d\n", getpid(), res); 55 | sleep(5); 56 | if (res != -1) 57 | { 58 | (void)close(res); 59 | } 60 | printf("Process %d finished\n", getpid()); 61 | exit (EXIT_SUCCESS); 62 | } 63 | -------------------------------------------------------------------------------- /Chapter13/fifo3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/fifo3 -------------------------------------------------------------------------------- /Chapter13/fifo3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 使用FIFO实现进程间通信 */ 11 | /* 本程序是生产者程序,它在需要时创建管道,然后尽可能 12 | 快的向管道中写入数据 13 | */ 14 | 15 | #define FIFO_NAME "/tmp/my_fifo" 16 | #define BUFFER_SIZE PIPE_BUF 17 | #define TEN_MEG (1024*1024*10) 18 | 19 | int main() 20 | { 21 | int pipe_fd; 22 | int res; 23 | int open_mode = O_WRONLY; 24 | int bytes_sent = 0; 25 | char buffer[BUFSIZ + 1]; 26 | 27 | /* 检查FIFO文件是否存在,若不存在则创建之 */ 28 | if (access(FIFO_NAME, F_OK) == -1) 29 | { 30 | res = mkfifo(FIFO_NAME, 0777); 31 | if (res != 0) 32 | { 33 | fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); 34 | exit (EXIT_FAILURE); 35 | } 36 | } 37 | 38 | printf("Process %d opening FIFO O_WRONLY\n", getpid()); 39 | /* 打开该FIFO文件 */ 40 | pipe_fd = open(FIFO_NAME, open_mode); 41 | printf("Process %d result %d\n", getpid(), pipe_fd); 42 | 43 | if (pipe_fd != -1) 44 | { 45 | /* 通过循环的方式向管道中写入数据 */ 46 | while (bytes_sent < TEN_MEG) 47 | { 48 | res = write(pipe_fd, buffer, BUFFER_SIZE); 49 | if (res == -1) 50 | { 51 | fprintf(stderr, "Write error on pipe\n"); 52 | exit (EXIT_FAILURE); 53 | } 54 | bytes_sent += res; 55 | } 56 | (void)close(pipe_fd); 57 | } 58 | else 59 | { 60 | exit (EXIT_FAILURE); 61 | } 62 | 63 | printf("Process %d finished\n", getpid()); 64 | exit (EXIT_SUCCESS); 65 | } 66 | -------------------------------------------------------------------------------- /Chapter13/fifo4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/fifo4 -------------------------------------------------------------------------------- /Chapter13/fifo4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 本程序是消费者程序,它从FIFO读取数据并丢弃他们 */ 11 | 12 | 13 | #define FIFO_NAME "/tmp/my_fifo" 14 | #define BUFFER_SIZE PIPE_BUF 15 | 16 | int main() 17 | { 18 | int pipe_fd; 19 | int res; 20 | int open_mode = O_RDONLY; 21 | char buffer[BUFFER_SIZE + 1]; 22 | int bytes_read = 0; 23 | 24 | memset(buffer, '\0', sizeof(buffer)); 25 | 26 | /* 以只读方式打开FIFO文件 */ 27 | printf("Process %d opening FIFO O_RDONLY\n", getpid()); 28 | pipe_fd = open(FIFO_NAME, open_mode); 29 | printf("Process %d result %d\n", getpid(), pipe_fd); 30 | 31 | if (pipe_fd != -1) 32 | { 33 | /* 循环读 */ 34 | do 35 | { 36 | res = read(pipe_fd, buffer, BUFFER_SIZE); 37 | bytes_read += res; 38 | } while(res > 0); 39 | (void)close(pipe_fd); 40 | } 41 | else 42 | { 43 | exit (EXIT_FAILURE); 44 | } 45 | printf("Process %d finished, %d bytes read\n", getpid(), bytes_read); 46 | exit (EXIT_SUCCESS); 47 | } 48 | -------------------------------------------------------------------------------- /Chapter13/pipe1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/pipe1 -------------------------------------------------------------------------------- /Chapter13/pipe1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int data_processed; 9 | int file_pipes[2]; 10 | const char some_data[] = "123"; 11 | char buffer[BUFSIZ + 1]; 12 | 13 | memset(buffer, '\0', sizeof(buffer)); 14 | 15 | /* 调用pipe函数在file_pipes数组中填上两个新的文件描述符 */ 16 | if (pipe(file_pipes) == 0) 17 | { 18 | /* 将数据写到file_pipes[1]中文件描述符中 */ 19 | data_processed = write(file_pipes[1], some_data, strlen(some_data)); 20 | printf("Wrote %d bytes\n", data_processed); 21 | /* 从file_pipes[0]中文件描述符以FIFO的方式读出数据 */ 22 | data_processed = read(file_pipes[0], buffer, BUFSIZ); 23 | printf("Read %d bytes: %s\n", data_processed, buffer); 24 | exit (EXIT_SUCCESS); 25 | } 26 | exit (EXIT_FAILURE); 27 | } 28 | -------------------------------------------------------------------------------- /Chapter13/pipe2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/pipe2 -------------------------------------------------------------------------------- /Chapter13/pipe2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 在不同的进程之间,进行数据读写操作 */ 7 | 8 | int main() 9 | { 10 | int data_processed; 11 | int file_pipes[2]; 12 | const char some_data[] = "123"; 13 | char buffer[BUFSIZ + 1]; 14 | pid_t fork_result; 15 | 16 | memset(buffer, '\0', sizeof(buffer)); 17 | /* 调用pipe函数在file_pipes中填充两个文件描述符 */ 18 | if (pipe(file_pipes) == 0) 19 | { 20 | /* 创建一个新进程 */ 21 | fork_result = fork(); 22 | if (fork_result == -1) 23 | { 24 | fprintf(stderr, "Fork failure"); 25 | exit (EXIT_FAILURE); 26 | } 27 | 28 | /* 如果是子进程 */ 29 | if (fork_result == 0) 30 | { 31 | /* 从第一个文件描述符处读数据 */ 32 | data_processed = read(file_pipes[0], buffer, BUFSIZ); 33 | printf("Read %d bytes: %s\n", data_processed, buffer); 34 | exit (EXIT_SUCCESS); 35 | } 36 | /* 如果是父进程 */ 37 | else 38 | { 39 | /* 从第二个文件描述符处写数据 */ 40 | data_processed = write(file_pipes[1], some_data, strlen(some_data)); 41 | printf("Wrote %d bytes\n", data_processed); 42 | } 43 | } 44 | exit (EXIT_SUCCESS); 45 | } 46 | -------------------------------------------------------------------------------- /Chapter13/pipe3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/pipe3 -------------------------------------------------------------------------------- /Chapter13/pipe3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 该程序是数据生产者,负责创建管道和启动子进程 */ 7 | 8 | /* 在不同的进程之间,进行数据读写操作 */ 9 | 10 | int main() 11 | { 12 | int data_processed; 13 | int file_pipes[2]; 14 | const char some_data[] = "123"; 15 | char buffer[BUFSIZ + 1]; 16 | pid_t fork_result; 17 | 18 | memset(buffer, '\0', sizeof(buffer)); 19 | /* 调用pipe函数在file_pipes中填充两个文件描述符 */ 20 | if (pipe(file_pipes) == 0) 21 | { 22 | /* 创建一个新进程 */ 23 | fork_result = fork(); 24 | if (fork_result == -1) 25 | { 26 | fprintf(stderr, "Fork failure"); 27 | exit (EXIT_FAILURE); 28 | } 29 | 30 | /* 如果是子进程 */ 31 | if (fork_result == 0) 32 | { 33 | /* 通过sprintf调用把 读取管道数据的文件描述符 保存到一个缓冲区中 */ 34 | sprintf(buffer, "%d", file_pipes[0]); 35 | /* 通过execl调用来启动pipe4程序,参数如下: 36 | ① 要启动的程序 37 | ② argv[0]:程序名 38 | ③ argv[1]:想让被调用程序去读取的文件描述符 39 | ④ (char *)0:终止被调用程序的参数列表 40 | */ 41 | (void)execl("pipe4", "pipe4", buffer, (char *)0); 42 | exit (EXIT_FAILURE); 43 | } 44 | /* 如果是父进程 */ 45 | else 46 | { 47 | /* 从第二个文件描述符处写数据 */ 48 | data_processed = write(file_pipes[1], some_data, strlen(some_data)); 49 | printf("%d - wrote %d bytes\n", getpid(), data_processed); 50 | } 51 | } 52 | exit (EXIT_SUCCESS); 53 | } 54 | -------------------------------------------------------------------------------- /Chapter13/pipe4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/pipe4 -------------------------------------------------------------------------------- /Chapter13/pipe4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 该程序是数据消费者,负责读取数据 */ 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | int data_processed; 11 | char buffer[BUFSIZ + 1]; 12 | int file_descriptor; 13 | 14 | memset(buffer, '\0', sizeof(buffer)); 15 | /* 获得作为参数传进来的文件描述符 */ 16 | sscanf(argv[1], "%d", &file_descriptor); 17 | /* 从文件描述符处读取数据 */ 18 | data_processed = read(file_descriptor, buffer, BUFSIZ); 19 | 20 | printf("%d - read %d bytes: %s\n", getpid(), data_processed, buffer); 21 | exit (EXIT_SUCCESS); 22 | } 23 | -------------------------------------------------------------------------------- /Chapter13/pipe5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/pipe5 -------------------------------------------------------------------------------- /Chapter13/pipe5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 父进程向管道中写数据 7 | 子进程中把标准输入与管道的读数据端相连,这样就可以直接从管道读取标准输入的数据 */ 8 | 9 | int main() 10 | { 11 | int data_processed; 12 | int file_pipes[2]; 13 | const char some_data[] = "123"; 14 | pid_t fork_result; 15 | 16 | /* 调用pipe函数填充file_pipes数组中的两个文件描述符 */ 17 | if (pipe(file_pipes) == 0) 18 | { 19 | /* 创建新进程 */ 20 | fork_result = fork(); 21 | if (fork_result == (pid_t)-1) 22 | { 23 | fprintf(stderr, "Fork failed"); 24 | exit (EXIT_FAILURE); 25 | } 26 | 27 | /* 如果是子进程 */ 28 | if (fork_result == (pid_t)0) 29 | { 30 | /* 关闭标准输入 */ 31 | close(0); 32 | /* 调用dup函数打开一个新的文件描述符,且该文件描述符是最小的数字0,即将标准输入与file_pipes[0]指向同一个文件 */ 33 | dup(file_pipes[0]); 34 | /* 子进程关闭 原先的 用来从管道读取数据的文件描述符file_pipes[0] */ 35 | close(file_pipes[0]); 36 | /* 子进程关闭 用来向管道写数据的文件描述符file_pipes[1] */ 37 | close(file_pipes[1]); 38 | execlp("od", "od", "-c", (char *)0); 39 | exit (EXIT_FAILURE); 40 | } 41 | /* 如果是主进程 */ 42 | else 43 | { 44 | /* 因为父进程不会从管道读数据,所以关闭读数据的文件描述符 */ 45 | close(file_pipes[0]); 46 | /* 父进程向管道写入数据 */ 47 | data_processed = write(file_pipes[1], some_data, strlen(some_data)); 48 | /* 父进程关闭管道的写入端,并退出 */ 49 | close(file_pipes[1]); 50 | printf("%d - wrote %d bytes\n", (int)getpid(), data_processed); 51 | } 52 | } 53 | exit (EXIT_SUCCESS); 54 | } 55 | -------------------------------------------------------------------------------- /Chapter13/popen1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/popen1 -------------------------------------------------------------------------------- /Chapter13/popen1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 本程序用popen调用启动带有-a选项的uname命令,然后用返回的文件流读取最多BUFSIZ个字符的数据,并将其显示在屏幕上 */ 7 | 8 | int main() 9 | { 10 | FILE *read_fp; 11 | /* BUFSIZ在stdio.h中,由#define语句定义 */ 12 | char buffer[BUFSIZ + 1]; 13 | int chars_read; 14 | /* 将buffer全部写NULL */ 15 | memset(buffer, '\0', sizeof(buffer)); 16 | /* 被调用程序(uname -a)的输出被调用程序(当前程序)使用 */ 17 | read_fp = popen("uname -a", "r"); 18 | if (read_fp != NULL) 19 | { 20 | /* 从返回的文件流中读取最多BUFSIZ个字符 */ 21 | chars_read = fread(buffer, sizeof(char), BUFSIZ , read_fp); 22 | if (chars_read > 0) 23 | { 24 | printf("Output was:-\n%s\n", buffer); 25 | } 26 | /* 关闭与之关联的文件流 */ 27 | pclose(read_fp); 28 | exit (EXIT_SUCCESS); 29 | } 30 | exit (EXIT_FAILURE); 31 | } 32 | -------------------------------------------------------------------------------- /Chapter13/popen2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/popen2 -------------------------------------------------------------------------------- /Chapter13/popen2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 本程序用带有参数"w"的popen命令启动od -c命令,然后向od -c命令发送一个字符串, 7 | 该命令接受字符串后,处理并将结果打印到屏幕上 8 | */ 9 | 10 | int main() 11 | { 12 | FILE *write_fp; 13 | char buffer[BUFSIZ + 1]; 14 | 15 | sprintf(buffer, "Once upon a time, there was ……\n"); 16 | /* 调用程序(当前程序)可以用fwrite函数向被调用程序(od -c)发送数据,而被调用程序可以在自己的标准输入上读取这些数据 */ 17 | write_fp = popen("od -c", "w"); 18 | if (write_fp != NULL) 19 | { 20 | fwrite(buffer, sizeof(char), strlen(buffer), write_fp); 21 | pclose(write_fp); 22 | exit (EXIT_SUCCESS); 23 | } 24 | exit (EXIT_FAILURE); 25 | } 26 | -------------------------------------------------------------------------------- /Chapter13/popen3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/popen3 -------------------------------------------------------------------------------- /Chapter13/popen3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 本程序演示当文件流中的数据过多时(超过BUFSIZ个),应该分块读取数据 */ 7 | 8 | int main() 9 | { 10 | FILE *read_fp; 11 | char buffer[BUFSIZ + 1]; 12 | int chars_read; 13 | 14 | memset(buffer, '\0', sizeof(buffer)); 15 | read_fp = popen("ps ax", "r"); 16 | if (read_fp != NULL) 17 | { 18 | /* 连续从文件流中读取数据,直到没有字符可以读 */ 19 | chars_read = fread(buffer, sizeof(char), BUFSIZ / 10, read_fp); 20 | while (chars_read > 0) 21 | { 22 | buffer[chars_read - 1] = '\0'; 23 | printf("Reading %d:-\n %s\n", BUFSIZ, buffer); 24 | chars_read = fread(buffer, sizeof(char), BUFSIZ / 10, read_fp); 25 | } 26 | pclose(read_fp); 27 | exit (EXIT_SUCCESS); 28 | } 29 | exit (EXIT_FAILURE); 30 | } 31 | -------------------------------------------------------------------------------- /Chapter13/popen4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/popen4 -------------------------------------------------------------------------------- /Chapter13/popen4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 在本程序中,在一个popen调用中启动了shell、cat命令和wc命令,并进行了一次输出重定向 */ 7 | /* 该程序的目的是统计当前目录下所有popen*.c文件的总行数 */ 8 | 9 | int main() 10 | { 11 | FILE *read_fp; 12 | char buffer[BUFSIZ + 1]; 13 | int chars_read; 14 | 15 | memset(buffer, '\0', sizeof(buffer)); 16 | read_fp = popen("cat popen*.c | wc -l", "r"); 17 | if (read_fp != NULL) 18 | { 19 | chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); 20 | while (chars_read > 0) 21 | { 22 | buffer[chars_read - 1] = '\0'; 23 | printf("Reading:-\n %s\n", buffer); 24 | chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); 25 | } 26 | pclose(read_fp); 27 | exit (EXIT_SUCCESS); 28 | } 29 | exit (EXIT_FAILURE); 30 | } 31 | -------------------------------------------------------------------------------- /Chapter13/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter13/server -------------------------------------------------------------------------------- /Chapter13/server.c: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | #include 3 | 4 | /* 本程序是服务器程序,创建并打开服务器管道,该管道被设置为只读的阻塞模式 */ 5 | 6 | int main() 7 | { 8 | int server_fifo_fd, client_fifo_fd; 9 | struct data_to_pass_st my_data; 10 | int read_res; 11 | char client_fifo[256]; 12 | char *tmp_char_ptr; 13 | 14 | mkfifo(SERVER_FIFO_NAME, 0777); 15 | 16 | /* 以只读的阻塞模式打开服务器管道 */ 17 | server_fifo_fd = open(SERVER_FIFO_NAME, O_RDONLY); 18 | if (server_fifo_fd == -1) 19 | { 20 | fprintf(stderr, "Server fifo failure\n"); 21 | exit (EXIT_FAILURE); 22 | } 23 | 24 | sleep(10); 25 | do 26 | { 27 | /* 读取客户发送来的数据 */ 28 | read_res = read(server_fifo_fd, &my_data, sizeof(my_data)); 29 | if (read_res > 0) 30 | { 31 | /* 将该临时指针指向结构体中的字符串 */ 32 | tmp_char_ptr = my_data.some_data; 33 | /* 通过循环的方式,将字符串中的每个字符都转为大写 */ 34 | while (*tmp_char_ptr) 35 | { 36 | *tmp_char_ptr = toupper(*tmp_char_ptr); 37 | tmp_char_ptr++; 38 | } 39 | /* 通过sprintf把CLIENT_FIFO_NAME和接收到额client_pid结合在一起 */ 40 | sprintf(client_fifo, CLIENT_FIFO_NAME, my_data.client_pid); 41 | 42 | /* 以只写的阻塞模式打开客户管道,把处理后的数据发送回去 */ 43 | client_fifo_fd = open(client_fifo, O_WRONLY); 44 | if (client_fifo_fd != -1) 45 | { 46 | /* 将处理后的数据通过客户管道写回去 */ 47 | write(client_fifo_fd, &my_data, sizeof(my_data)); 48 | close(client_fifo_fd); 49 | } 50 | } 51 | } while (read_res > 0); 52 | /* 关闭服务器管道的文件描述符,删除FIFO文件,然后退出 */ 53 | close(server_fifo_fd); 54 | unlink(SERVER_FIFO_NAME); 55 | exit (EXIT_SUCCESS); 56 | } 57 | -------------------------------------------------------------------------------- /Chapter14/msg1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter14/msg1 -------------------------------------------------------------------------------- /Chapter14/msg1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | /* 该程序用于从消息队列中接收消息 */ 10 | 11 | struct my_msg_st 12 | { 13 | long int my_msg_type; 14 | char some_text[BUFSIZ]; 15 | }; 16 | 17 | int main() 18 | { 19 | int running = 1; 20 | int msgid; 21 | struct my_msg_st some_data; 22 | long int msg_to_receive = 0; 23 | 24 | /* 获取消息队列的标识符 */ 25 | msgid = msgget((key_t)1234, 0666 | IPC_CREAT); 26 | 27 | if (msgid == -1) 28 | { 29 | fprintf(stderr, "msgget failed with error: %d\n", errno); 30 | exit (EXIT_FAILURE); 31 | } 32 | 33 | /* 从消息队列中读取消息,直到遇到end字符串为止 */ 34 | while (running) 35 | { 36 | if (msgrcv(msgid, (void *)&some_data, BUFSIZ, msg_to_receive, 0) == -1) 37 | { 38 | fprintf(stderr, "msgrcv failed with error :%d\n", errno); 39 | exit (EXIT_FAILURE); 40 | } 41 | 42 | printf("You wrote: %s", some_data.some_text); 43 | if (strncmp(some_data.some_text, "end", 3) == 0) 44 | { 45 | running = 0; 46 | } 47 | } 48 | 49 | /* 删除消息队列并退出 */ 50 | if (msgctl(msgid, IPC_RMID, 0) == -1) 51 | { 52 | fprintf(stderr, "msgctl(IPC_RMID) failed\n"); 53 | exit (EXIT_FAILURE); 54 | } 55 | 56 | exit (EXIT_SUCCESS); 57 | } 58 | -------------------------------------------------------------------------------- /Chapter14/msg2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter14/msg2 -------------------------------------------------------------------------------- /Chapter14/msg2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | /* 该程序用于发送消息 */ 10 | 11 | #define MAX_TEXT 512 12 | 13 | struct my_msg_st 14 | { 15 | long int my_msg_type; 16 | char some_text[MAX_TEXT]; 17 | }; 18 | 19 | int main() 20 | { 21 | int running = 1; 22 | struct my_msg_st some_data; 23 | int msgid; 24 | char buffer[BUFSIZ]; 25 | 26 | /* 创建消息队列,使用关键字1234 */ 27 | msgid = msgget((key_t)1234, 0666 | IPC_CREAT); 28 | 29 | if (msgid == -1) 30 | { 31 | fprintf(stderr, "msgget faield with error: %d\n", errno); 32 | exit (EXIT_FAILURE); 33 | } 34 | 35 | while (running) 36 | { 37 | printf("Enter some text: "); 38 | fgets(buffer, BUFSIZ, stdin); 39 | some_data.my_msg_type = 1; 40 | strcpy(some_data.some_text, buffer); 41 | 42 | /* 调用msgsnd函数向消息队列中发送消息 */ 43 | if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) 44 | { 45 | fprintf(stderr, "msgsnd failed\n"); 46 | exit (EXIT_FAILURE); 47 | } 48 | 49 | /* 如果检测到字符串end,则退出程序 */ 50 | if (strncmp(buffer, "end", 3) == 0) 51 | { 52 | running = 0; 53 | } 54 | } 55 | exit (EXIT_SUCCESS); 56 | } 57 | -------------------------------------------------------------------------------- /Chapter14/sem1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter14/sem1 -------------------------------------------------------------------------------- /Chapter14/semun.h: -------------------------------------------------------------------------------- 1 | #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) 2 | /* union semun is defined by including */ 3 | #else 4 | /* according to X/OPEN we have to define it ourselves */ 5 | union semun { 6 | int val; /* value for SETVAL */ 7 | struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ 8 | unsigned short int *array; /* array for GETALL, SETALL */ 9 | struct seminfo *__buf; /* buffer for IPC_INFO */ 10 | }; 11 | #endif 12 | -------------------------------------------------------------------------------- /Chapter14/shm1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter14/shm1 -------------------------------------------------------------------------------- /Chapter14/shm1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include "shm_com.h" 8 | 9 | /* 消费者程序将创建一个共享内存段,把写到它里面的数据都显示出来 */ 10 | 11 | int main() 12 | { 13 | int running = 1; 14 | void *shared_memory = (void *)0; 15 | struct shared_use_st *shared_stuff; 16 | int shmid; 17 | 18 | srand((unsigned int)getpid()); 19 | 20 | /* 调用shmget函数来创建一个共享内存,该函数返回共享内存标识符 */ 21 | shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT); 22 | 23 | if (shmid == -1) 24 | { 25 | fprintf(stderr, "shmget failed\n"); 26 | exit (EXIT_FAILURE); 27 | } 28 | 29 | /* 第一次创建共享内存后,要想使其能够被访问,必须将其连接到一个进程的地址空间中 */ 30 | /* shmat调用成功后,将返回指向共享内存第一个字节的指针 */ 31 | shared_memory = shmat(shmid, (void *)0, 0); 32 | if (shared_memory == (void *)-1) 33 | { 34 | fprintf(stderr, "shmat failed\n"); 35 | exit (EXIT_FAILURE); 36 | } 37 | printf("Memory attached at %X\n", (int)shared_memory); 38 | 39 | shared_stuff = (struct shared_use_st *)shared_memory; 40 | shared_stuff->written_by_you = 0; 41 | while (running) 42 | { 43 | if (shared_stuff->written_by_you) 44 | { 45 | printf("You wrote: %s", shared_stuff->some_text); 46 | sleep(rand() % 4); 47 | shared_stuff->written_by_you = 0; 48 | /* 当读取到end字符串时,退出while循环 */ 49 | if (strncmp(shared_stuff->some_text, "end", 3) == 0) 50 | { 51 | running = 0; 52 | } 53 | } 54 | } 55 | 56 | /* 将共享内存分离,并删除 */ 57 | if (shmdt(shared_memory) == -1) 58 | { 59 | fprintf(stderr, "shmdt failed\n"); 60 | exit (EXIT_FAILURE); 61 | } 62 | 63 | /* 通过command参数IPC_RMID将内存段删除 */ 64 | if (shmctl(shmid, IPC_RMID, 0) == -1) 65 | { 66 | fprintf(stderr, "shmctl(IPC_RMID) failed\n"); 67 | exit (EXIT_FAILURE); 68 | } 69 | 70 | exit (EXIT_SUCCESS); 71 | } 72 | -------------------------------------------------------------------------------- /Chapter14/shm2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter14/shm2 -------------------------------------------------------------------------------- /Chapter14/shm2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include "shm_com.h" 8 | 9 | /* 生产者程序连接一个共享内存段,并向其中写入数据 */ 10 | 11 | int main() 12 | { 13 | int running = 1; 14 | void *shared_memory = (void *)0; 15 | struct shared_use_st *shared_stuff; 16 | char buffer[BUFSIZ]; 17 | int shmid; 18 | 19 | /* 调用shmget函数来创建一个共享内存段 */ 20 | shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT); 21 | 22 | if (shmid == -1) 23 | { 24 | fprintf(stderr, "shmget failed\n"); 25 | exit (EXIT_FAILURE); 26 | } 27 | 28 | /* 第一次创建共享内存后,必须将其与进程的地址空间连接才能被访问 */ 29 | /* 调用shmat函数成功后,返回指向共享内存的第一个字节的指针 */ 30 | shared_memory = shmat(shmid, (void *)0, 0); 31 | if (shared_memory == (void *)-1) 32 | { 33 | fprintf(stderr, "shmat failed\n"); 34 | exit (EXIT_FAILURE); 35 | } 36 | 37 | /* 显示上面函数调用后,共享内存与地址空间的哪个地方相连接 */ 38 | printf("Memory attahed at %X\n", (int)shared_memory); 39 | shared_stuff = (struct shared_use_st *)shared_memory; 40 | while (running) 41 | { 42 | /* 该标志位为1时,表明消费者程序正在从共享内存读取数据 */ 43 | while (shared_stuff->written_by_you == 1) 44 | { 45 | sleep(1); 46 | printf("waiting for client……\n"); 47 | } 48 | printf("Enter some text: "); 49 | fgets(buffer, BUFSIZ, stdin); 50 | 51 | /* 向共享内存写入数据,并将标志位置1 */ 52 | strncpy(shared_stuff->some_text, buffer, TEXT_SZ); 53 | shared_stuff->written_by_you = 1; 54 | 55 | /* 当检测到输入中有end字符串时,结束读取字符串 */ 56 | if (strncmp(buffer, "end", 3) == 0) 57 | { 58 | running = 0; 59 | } 60 | } 61 | 62 | /* 将共享内存与进程分离 */ 63 | if (shmdt(shared_memory) == -1) 64 | { 65 | fprintf(stderr, "shamdt failed\n"); 66 | exit (EXIT_FAILURE); 67 | } 68 | 69 | exit (EXIT_SUCCESS); 70 | } 71 | -------------------------------------------------------------------------------- /Chapter14/shm_com.h: -------------------------------------------------------------------------------- 1 | /* 定义需要传输的文本长度为2K */ 2 | #define TEXT_SZ 2048 3 | 4 | struct shared_use_st 5 | { 6 | /* 当有数据写入这个结构时,用该整形变量通知消费者 */ 7 | int written_by_you; 8 | char some_text[TEXT_SZ]; 9 | }; 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter15/client1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/client1 -------------------------------------------------------------------------------- /Chapter15/client1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int sockfd; 11 | int len; 12 | struct sockaddr_un address; 13 | int result; 14 | char ch = 'A'; 15 | 16 | /* 为客户创建一个套接字 */ 17 | sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 18 | 19 | /* 根据服务器的情况给套接字命名 */ 20 | address.sun_family = AF_UNIX; 21 | /* 服务器的套接字名为 server_socket */ 22 | strcpy(address.sun_path, "server_socket"); 23 | len = sizeof(address); 24 | 25 | /* 将客户端的套接字连接到服务器的套接字 */ 26 | result = connect(sockfd, (struct sockaddr *)&address, len); 27 | 28 | if (result == -1) 29 | { 30 | perror("oops: client1"); 31 | exit (1); 32 | } 33 | 34 | /* 通过sockfd进行读写操作 */ 35 | /* 先通过套接字向服务器写一个字符,然后在读取服务器返回的字符,最后在终端显示该字符 */ 36 | write(sockfd, &ch, 1); 37 | read(sockfd, &ch, 1); 38 | printf("char from server = %c\n", ch); 39 | close(sockfd); 40 | exit (0); 41 | } 42 | -------------------------------------------------------------------------------- /Chapter15/client2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/client2 -------------------------------------------------------------------------------- /Chapter15/client2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 该程序是客户端程序,它通过回路网络(lookback)连接到一个网络套接字 10 | 该程序试图连接到IP地址为127.0.0.1的主机上的服务器 11 | */ 12 | 13 | /* 该程序中有一个关于硬件的微小错误:即Intel和IBMPowerPC的大小端表示 14 | 不同的计算机使用不同的字节序来表示整数 15 | Intel 32位 int 4字节 字节序:1-2-3-4 16 | IBMPowerPC 32位 int 4字节 字节序:4-3-2-1 17 | */ 18 | 19 | 20 | 21 | int main() 22 | { 23 | int sockfd; 24 | int len; 25 | struct sockaddr_in address; 26 | int result; 27 | char ch = 'A'; 28 | 29 | /* 为客户端创建一个套接字 */ 30 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 31 | 32 | /* 为服务器套接字命名 */ 33 | address.sin_family = AF_INET; 34 | /* 使用inet_addr函数将IP地址的文本表示方式转换为符合套接字地址要求的格式 */ 35 | address.sin_addr.s_addr = inet_addr("127.0.0.1"); 36 | address.sin_port = 9734; 37 | len = sizeof(address); 38 | 39 | /* 将客户端套接字与服务器套接字相连接 */ 40 | result = connect(sockfd, (struct sockaddr *)&address, len); 41 | 42 | if (result == -1) 43 | { 44 | perror("oops:client2"); 45 | exit (1); 46 | } 47 | 48 | /* 通过套接字进行读写操作 */ 49 | write(sockfd, &ch, 1); 50 | read(sockfd, &ch, 1); 51 | printf("char from server = %c\n", ch); 52 | close(sockfd); 53 | exit (0); 54 | } 55 | -------------------------------------------------------------------------------- /Chapter15/client3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/client3 -------------------------------------------------------------------------------- /Chapter15/client3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 该程序是客户端程序,它通过回路网络(lookback)连接到一个网络套接字 10 | 该程序试图连接到IP地址为127.0.0.1的主机上的服务器 11 | */ 12 | 13 | /* 该程序中有一个关于硬件的微小错误:即Intel和IBMPowerPC的大小端表示 14 | 不同的计算机使用不同的字节序来表示整数 15 | Intel 32位 int 4字节 字节序:1-2-3-4 16 | IBMPowerPC 32位 int 4字节 字节序:4-3-2-1 17 | */ 18 | 19 | /* Note:上面的BUG已修复 20 | unsigned long int htonl(unsigned long int hostlong); 21 | 长整数从主机字节序到网络字节序的转换 22 | unsigned short int htons(unsigned short int hostshort); 23 | 短整数从主机字节序到网络字节序的转换 24 | */ 25 | 26 | 27 | 28 | int main() 29 | { 30 | int sockfd; 31 | int len; 32 | struct sockaddr_in address; 33 | int result; 34 | char ch = 'A'; 35 | 36 | /* 为客户端创建一个套接字 */ 37 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 38 | 39 | /* 为服务器套接字命名 */ 40 | address.sin_family = AF_INET; 41 | /* 使用inet_addr函数将IP地址的文本表示方式转换为符合套接字地址要求的格式 */ 42 | /* 不需要对函数调用inet_addr进行转换,因为该函数已被定义为产生一个网络字节序 */ 43 | address.sin_addr.s_addr = inet_addr("127.0.0.1"); 44 | address.sin_port = htons(9734); 45 | len = sizeof(address); 46 | 47 | /* 将客户端套接字与服务器套接字相连接 */ 48 | result = connect(sockfd, (struct sockaddr *)&address, len); 49 | 50 | if (result == -1) 51 | { 52 | perror("oops:client3"); 53 | exit (1); 54 | } 55 | 56 | /* 通过套接字进行读写操作 */ 57 | write(sockfd, &ch, 1); 58 | read(sockfd, &ch, 1); 59 | printf("char from server = %c\n", ch); 60 | close(sockfd); 61 | exit (0); 62 | } 63 | -------------------------------------------------------------------------------- /Chapter15/getdate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/getdate -------------------------------------------------------------------------------- /Chapter15/getdate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 该程序尝试连接到指定主机返回的地址列表中的第一个地址,如果成功, 9 | 就读取daytime服务返回的信息 10 | */ 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | char *host; 15 | int sockfd; 16 | int len, result; 17 | struct sockaddr_in address; 18 | struct hostent *hostinfo; 19 | struct servent *servinfo; 20 | char buffer[128]; 21 | 22 | if (argc == 1) 23 | { 24 | host = "localhost"; 25 | } 26 | else 27 | { 28 | host = argv[1]; 29 | } 30 | 31 | /* 按照主机名字查找主机的信息 */ 32 | hostinfo = gethostbyname(host); 33 | if (!hostinfo) 34 | { 35 | fprintf(stderr, "no host: %s\n", host); 36 | exit (1); 37 | } 38 | 39 | /* 检查主机上是否有daytime服务 */ 40 | servinfo = getservbyname("daytime", "tcp"); 41 | if (!servinfo) 42 | { 43 | fprintf(stderr, "no daytime service\n"); 44 | exit (1); 45 | } 46 | printf("daytime port is %d\n", ntohs(servinfo->s_port)); 47 | 48 | /* 创建一个套接字 */ 49 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 50 | 51 | /* 构造address结构体 */ 52 | address.sin_family = AF_INET; 53 | address.sin_port = servinfo->s_port; 54 | address.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list; 55 | len = sizeof(address); 56 | 57 | /* 建立连接,并获取有关信息 */ 58 | result = connect(sockfd, (struct sockaddr *)&address, len); 59 | if (result == -1) 60 | { 61 | perror("oops: getdate"); 62 | exit (1); 63 | } 64 | 65 | result = read(sockfd, buffer, sizeof(buffer)); 66 | buffer[result] = '\0'; 67 | printf("read %d bytes: %s", result, buffer); 68 | 69 | close(sockfd); 70 | exit (0); 71 | } 72 | -------------------------------------------------------------------------------- /Chapter15/getname: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/getname -------------------------------------------------------------------------------- /Chapter15/getname.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | char *host, **names, **addrs; 11 | struct hostent *hostinfo; 12 | 13 | /* 把host变量设置为程序的命令行参数,或者默认设置为用户主机的主机名 */ 14 | if (argc == 1) 15 | { 16 | char myname[256]; 17 | gethostname(myname, 255); 18 | host = myname; 19 | } 20 | else 21 | { 22 | host = argv[1]; 23 | } 24 | 25 | /* 调用gethostbyname从主机数据库中通过主机名来获取主机的信息 */ 26 | hostinfo = gethostbyname(host); 27 | /* 若不存在该主机,则显示错误消息 */ 28 | if (!hostinfo) 29 | { 30 | fprintf(stderr, "cannot get info for host: %s\n", host); 31 | exit (1); 32 | } 33 | 34 | /* 显示主机名和可能的别名 */ 35 | printf("results for host %s:\n", host); 36 | printf("Name: %s\n", hostinfo->h_name); 37 | printf("Aliases:"); 38 | 39 | names = hostinfo->h_aliases; 40 | while (*names) 41 | { 42 | printf(" %s",*names); 43 | names++; 44 | } 45 | printf("\n"); 46 | 47 | /* 判断被查询的主机是不是一个IP主机 */ 48 | if (hostinfo->h_addrtype != AF_INET) 49 | { 50 | fprintf(stderr, "not an IP host!\n"); 51 | exit (1); 52 | } 53 | 54 | /* 显示IP的地址列表 */ 55 | addrs = hostinfo->h_addr_list; 56 | while (*addrs) 57 | { 58 | printf(" %s", inet_ntoa(*(struct in_addr *)*addrs)); 59 | addrs++; 60 | } 61 | 62 | printf("\n"); 63 | exit (0); 64 | } 65 | -------------------------------------------------------------------------------- /Chapter15/select: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/select -------------------------------------------------------------------------------- /Chapter15/select.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 该程序读取键盘(标准输入),超时时间设为2.5秒 10 | 该程序只在有输入就绪时才读取键盘 11 | */ 12 | 13 | int main() 14 | { 15 | char buffer[128]; 16 | int result, nread; 17 | 18 | /* fd_set:一种数据结构,已打开的文件描述符的集合 */ 19 | fd_set inputs, testfds; 20 | struct timeval timeout; 21 | 22 | FD_ZERO(&inputs); 23 | /* 将文件描述符集合设置为标准输入stdin */ 24 | FD_SET(0, &inputs); 25 | 26 | /* 在标准输入上最多等待2.5秒 */ 27 | while (1) 28 | { 29 | testfds = inputs; 30 | timeout.tv_sec = 2; 31 | timeout.tv_usec = 500000; 32 | 33 | result = select(FD_SETSIZE, &testfds, (fd_set *)NULL, (fd_set *)NULL, &timeout); 34 | 35 | /* 对result进行测试: 36 | 若没有输入,则程序循环; 37 | 若出现一个错误,则程序退出; 38 | 否则,程序就读取标准输入stdin上的输入,并在接受到行尾字符后把他们都回显到屏幕上 39 | */ 40 | switch(result) 41 | { 42 | case 0: 43 | printf("timeout\n"); 44 | break; 45 | case -1: 46 | perror("select"); 47 | exit (1); 48 | default: 49 | /* 调用FD_ISSET函数来检测哪些文件描述符发生了变化 */ 50 | if (FD_ISSET(0, &testfds)) 51 | { 52 | /* 得到标准输入里有多少字节需要读取,然后将该数值放到nread中 */ 53 | ioctl(0, FIONREAD, &nread); 54 | if (nread == 0) 55 | { 56 | printf("keyboard done\n"); 57 | exit (0); 58 | } 59 | /* 通过read函数读取标准输入中的字节 */ 60 | nread = read(0, buffer, nread); 61 | buffer[nread] = 0; 62 | printf("read %d from keyboard: %s", nread, buffer); 63 | } 64 | break; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Chapter15/server1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/server1 -------------------------------------------------------------------------------- /Chapter15/server1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int server_sockfd, client_sockfd; 11 | int server_len, client_len; 12 | struct sockaddr_un server_address; 13 | struct sockaddr_un client_address; 14 | 15 | /* 删除以前的套接字,为服务器创建一个未命名的套接字 */ 16 | unlink("server socket"); 17 | server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 18 | 19 | /* 命名套接字 */ 20 | server_address.sun_family = AF_UNIX; 21 | strcpy(server_address.sun_path, "server_socket"); 22 | server_len = sizeof(server_address); 23 | /* 调用bind函数来给套接字绑定一个名字 */ 24 | /* 把server_address中的信息与server_sockfd相关联 */ 25 | bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 26 | 27 | /* 创建一个监听队列, 开始等待客户进行连接 */ 28 | listen(server_sockfd, 5); 29 | while (1) 30 | { 31 | char ch; 32 | printf("server waiting\n"); 33 | /* 接受一个连接 */ 34 | client_len = sizeof(client_address); 35 | 36 | /* 处理排在套接字队列中的第一个未处理连接,accept函数创建一个新套接字来与该客户进行通信 */ 37 | /* 连接客户的地址被放入client_address结构中 */ 38 | client_sockfd = accept(server_sockfd, (struct address *)&client_address, &client_len); 39 | 40 | /* 对client_sockfd套接字上的客户进行读写操作 */ 41 | read(client_sockfd, &ch, 1); 42 | ch++; 43 | write(client_sockfd, &ch, 1); 44 | close(client_sockfd); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Chapter15/server2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/server2 -------------------------------------------------------------------------------- /Chapter15/server2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 该程序中有一个关于硬件的微小错误:即Intel和IBMPowerPC的大小端表示 10 | 不同的计算机使用不同的字节序来表示整数 11 | Intel 32位 int 4字节 字节序:1-2-3-4 12 | IBMPowerPC 32位 int 4字节 字节序:4-3-2-1 13 | */ 14 | 15 | int main() 16 | { 17 | int server_sockfd, client_sockfd; 18 | int server_len, client_len; 19 | struct sockaddr_in server_address; 20 | struct sockaddr_in client_address; 21 | 22 | /* 为服务器创建一个未命名套接字 */ 23 | server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 24 | 25 | /* 命名该套接字 */ 26 | server_address.sin_family = AF_INET; 27 | server_address.sin_addr.s_addr = inet_addr("127.0.01"); 28 | server_address.sin_port = 9734; 29 | server_len = sizeof(server_address); 30 | bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 31 | 32 | /* 创建监听队列 */ 33 | listen(server_sockfd, 5); 34 | while (1) 35 | { 36 | char ch; 37 | printf("server waiting\n"); 38 | 39 | /* 接受一个连接 */ 40 | client_len = sizeof(client_address); 41 | client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len); 42 | 43 | read(client_sockfd, &ch, 1); 44 | ch++; 45 | write(client_sockfd, &ch, 1); 46 | close(client_sockfd); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter15/server3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/server3 -------------------------------------------------------------------------------- /Chapter15/server3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 该程序中有一个关于硬件的微小错误:即Intel和IBMPowerPC的大小端表示 10 | 不同的计算机使用不同的字节序来表示整数 11 | Intel 32位 int 4字节 字节序:1-2-3-4 12 | IBMPowerPC 32位 int 4字节 字节序:4-3-2-1 13 | */ 14 | 15 | /* Note:上面的BUG已修复 16 | unsigned long int htonl(unsigned long int hostlong); 17 | 长整数从主机字节序到网络字节序的转换 18 | unsigned short int htons(unsigned short int hostshort); 19 | 短整数从主机字节序到网络字节序的转换 20 | */ 21 | 22 | 23 | int main() 24 | { 25 | int server_sockfd, client_sockfd; 26 | int server_len, client_len; 27 | struct sockaddr_in server_address; 28 | struct sockaddr_in client_address; 29 | 30 | /* 为服务器创建一个未命名套接字 */ 31 | server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 32 | 33 | /* 命名该套接字 */ 34 | server_address.sin_family = AF_INET; 35 | /* INADDR_ANY表示允许到达服务器任一网络接口的连接 */ 36 | server_address.sin_addr.s_addr = htonl(INADDR_ANY); 37 | server_address.sin_port = htons(9734); 38 | server_len = sizeof(server_address); 39 | bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 40 | 41 | /* 创建监听队列 */ 42 | listen(server_sockfd, 5); 43 | while (1) 44 | { 45 | char ch; 46 | printf("server waiting\n"); 47 | 48 | /* 接受一个连接 */ 49 | client_len = sizeof(client_address); 50 | client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len); 51 | 52 | read(client_sockfd, &ch, 1); 53 | ch++; 54 | write(client_sockfd, &ch, 1); 55 | close(client_sockfd); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Chapter15/server4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/server4 -------------------------------------------------------------------------------- /Chapter15/server4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 该程序是服务器程序,它能同时处理多个客户端的连接请求 10 | 该进程通过为每个客户创建一个子进程来处理多个请求 11 | */ 12 | 13 | int main() 14 | { 15 | int server_sockfd, client_sockfd; 16 | int server_len, client_len; 17 | struct sockaddr_in server_address; 18 | struct sockaddr_in client_address; 19 | 20 | server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 21 | 22 | server_address.sin_family = AF_INET; 23 | server_address.sin_addr.s_addr = htonl(INADDR_ANY); 24 | server_address.sin_port = htons(9734); 25 | server_len = sizeof(server_address); 26 | 27 | bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 28 | 29 | /* 创建一个连接队列 */ 30 | listen(server_sockfd, 5); 31 | 32 | /* 设置SIGCHLD信号以避免出现僵尸进程 */ 33 | signal(SIGCHLD, SIG_IGN); 34 | 35 | while (1) 36 | { 37 | char ch; 38 | printf("server waiting\n"); 39 | 40 | /* 接受客户的连接 */ 41 | client_len = sizeof(client_address); 42 | client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len); 43 | 44 | /* 通过fork调用为该客户创建一个子进程,并判断是在子进程还是父进程中 */ 45 | if (fork() == 0) 46 | { 47 | /* 在子进程中 */ 48 | read(client_sockfd, &ch, 1); 49 | /* 该5秒延时是为了模拟服务器的计算时间或数据库访问时间 */ 50 | sleep(5); 51 | ch++; 52 | write(client_sockfd, &ch, 1); 53 | close(client_sockfd); 54 | exit (0); 55 | } 56 | else 57 | { 58 | /* 在父进程中 */ 59 | /* 关闭该客户 */ 60 | close(client_sockfd); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Chapter15/server5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scnb/Beginning-Linux-Programming/6345773c952b4ee278ecc56062aebd4674bd63b4/Chapter15/server5 -------------------------------------------------------------------------------- /Chapter15/server5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 该程序让select函数同时检查(监听套接字)和(客户的连接套接字), 11 | 一旦select函数发现有活动发生,就调用FD_ISSET函数遍历所有的文件 12 | 描述符,以检查是哪个文件描述符上有活动发生 13 | */ 14 | 15 | int main() 16 | { 17 | int server_sockfd, client_sockfd; 18 | int server_len, client_len; 19 | struct sockaddr_in server_address; 20 | struct sockaddr_in client_address; 21 | int result; 22 | fd_set readfds, testfds; 23 | 24 | /* 为服务器创建并命名一个套接字 */ 25 | server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 26 | 27 | server_address.sin_family = AF_INET; 28 | server_address.sin_addr.s_addr = htonl(INADDR_ANY); 29 | server_address.sin_port = htons(9734); 30 | server_len = sizeof(server_address); 31 | 32 | bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 33 | 34 | /* 创建一个连接队列,初始化readfds以处理来自server_sockfd的输入 */ 35 | listen(server_sockfd, 5); 36 | 37 | FD_ZERO(&readfds); 38 | FD_SET(server_sockfd, &readfds); 39 | 40 | /* 开始等待客户和请求的到来 */ 41 | while (1) 42 | { 43 | char ch; 44 | int fd; 45 | int nread; 46 | 47 | testfds = readfds; 48 | 49 | printf("server waiting\n"); 50 | result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); 51 | 52 | if (result < 1) 53 | { 54 | perror("server5"); 55 | exit (1); 56 | } 57 | 58 | /* 用FD_ISSET来依次检测每个描述符,以发现活动发生在哪个描述符上 */ 59 | for (fd = 0; fd < FD_SETSIZE; fd++) 60 | { 61 | if (FD_ISSET(fd, &testfds)) 62 | { 63 | /* 如果活动发生在套接字server_sockfd上,则表明是一个新的连接请求 */ 64 | if (fd == server_sockfd) 65 | { 66 | client_len = sizeof(client_address); 67 | client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len); 68 | FD_SET(client_sockfd, &readfds); 69 | printf("adding client on fd %d\n", client_sockfd); 70 | } 71 | /* 否则 就是客户的活动 */ 72 | else 73 | { 74 | ioctl(fd, FIONREAD, &nread); 75 | 76 | /* 若客户没有发送任何字节,则表明客户要退出,则执行close */ 77 | if (nread == 0) 78 | { 79 | close(fd); 80 | FD_CLR(fd, &readfds); 81 | printf("removing client on fd %d\n", fd); 82 | } 83 | /* 否则就将客户发送的字符加1再写回给客户 */ 84 | else 85 | { 86 | read(fd, &ch, 1); 87 | sleep(5); 88 | printf("serving client on fd %d\n", fd); 89 | ch++; 90 | write(fd, &ch, 1); 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Beginning-Linux-Programming 2 | Linux程序设计 中文版 第四版 实现书上代码 3 | 4 | 图书信息: 5 | 《Beginning Linux Programming 4th Edition》 6 | 7 | 作者: 8 | Neil matthew 9 | Richard Stones 10 | 11 | --------------------------------------------------------------------------------