Основи linux кодинга. Частина 1.
Привіт всім.
Мета даної статті розповісти читачам про засади linux програмування з допомогою системних викликів.
Як компілятора будемо використовувати gcc, які входить у поставку більшості дистрибутивів. Ще нам знадобиться make
Інструменти
Перед тим як почати програмувати, варто розібрати, що нам допоможе в цьому.
Для початку компілятор gcc(GNU project C Compiler):
Приклад найпростішого використання: БВг>
$gcc /proga.c -o /ргодили так:
$gcc -o /prog /proga.c

Ключ -o вказуємо ім’я і шлях до майбутнього бинарнику
Якщо у вихідному тексті є помилки, то розумний компілятор вкаже на них.
Мани:
www.linuxcenter.ru/lib/books/linuxdev/linuxdev1.phtml
skif.bas-net.by/bsuir/prog_in_linux/node3.html

Make — програма може складатися з безлічі файлів, які потрібно зібрати в один.
Якщо файлів мало то можна зібрати використовую тільки gcc, але файлів може бути дуже багато. Саме для таких випадків і застосовуємо складальник Make. Для її роботи необхідно використовувати makefile — спеціальні файли зі сценарієм складання.Що б краще зрозуміти ці сценарії давайте спробуємо зібрати програму, що складається з двох частин з допомогою gcc:
У нас є файл main.c і modul.c:
$gcc – c main.c
$gcc – c modul.c
Тут ми вказали ключ -c, він означає, що потрібно зібрати об’єктний файл, це ще не є повноцінною програмою, її ми зберемо далі:
$ gcc -o programm main.o modul.c

Тепер ми зібрали бінарники з двох файлів.
Отже, повернемося до make, як я вже говорив файлів для складання може бути дуже багато, тому використовуємо makefile.
Спробуємо зробити його самим:
hello:
main.o programm.o
gcc -o programm main.o modul.o

main.o:
main.c
gcc -c main.c

modul.o:
modul.c
gcc -c modul.c

clean:
rm -f *.o programm

Думаю все ясно. Ми виконуємо майже ті ж дії, що й вище, але вже автоматично.
У розділі Clean ми відчищаємо директорію від тимчасових файлів. Так, і не забуваємо про знаки табуляції, вони дуже важныВот мануал для самостійного вивчення
www.linuxrsp.ru/docs/gm.html
Тягнути не будемо, а перейдемо до справи.
Для початку визначимося, що таке системний виклик:
Системний виклик це звернення, який або прикладної програми до ядру ОС, для виконання якої-небудь операції.

Першим, як думаю самим нескладним, ми розберемо роботу з файлами.

Загальне уявлення про роботу з файлами
Для роботи з файлами в linux існують виклики open, creat, write, read. Думаю, зміст їх зрозумілий. Розберемо, як вони працюють.
open(char *filename, int mode);
По-перше, функція повертає -1 при помилці. Якщо все нормально, то повертає дескриптор файлу.char *filename — ім’я/шлях файлу
int mode — режим, з яким потрібно відкрити, тобто що потрібно робити з файлом — читати, писати чи читати і писати (=)
O_RDONLY — читання
O_WRONLY — запис
O_RDWR — читання і запис
Для використання цієї функції потрібно підключити модуль fcntl.h
Приклад:
—–
open(“/var/log”,O_RDONLY);
—–

read(int d, char *buf, size_t countb);

Аналогічно попередньої функції повертається -1 при помилку, а якщо немає помилок, то ціле число.

int d — джерело, тобто дескриптор, тобто результат виконання функції open.
char *buf — місце, куди будуть зчитані дані.
size_t countb — ну і кількість байт, які потрібно вважати.
Для використання підключаємо модуль unistd.h
Приклад

—–

int d=open(‘/var/log/’,RDONLY);
char *buf;
size_t count b=1024;
read(d,buf,countb)
—–

creat(char *name, mode_t right);

char *name — ім’я створюваного файлу
mode_t right — права на доступ
При помилку -1.
Для роботи підключаємо модуль fcntl.h

Приклад
creat(“/home/stranger/myfile”,754)

write(int d, char *buff,size_ size);

int d дескриптор файлу для запису
har *buff самі дані які потрібно записати
size_ size кількість байт при запису
-1 при помилці, для використання підключаємо unistd.h

І наприкінці варто сказати про –

close(int d);
Єдиний аргумент, який потрібно передати функції, це дескриптор відкритого файлу. І функція закриває файл.

Ну що ж, прийшов час написати повноцінний приклад.
Почнемо з простенької програми для копіювання файлів.
В якості аргументів вона буде приймати ім’я/шлях вихідного файлу і ім’я/шлях
скопійованого файлу.
Значить спочатку відкриваємо вихідний файл (open) і зчитуємо його(read). Далі створюємо файл (create) і записуємо в нього зчитаний перший файл (write).

#include [stdio.h]
#include [unistd.h]
#include [fcntl.h]
#include [stdlib.h]
#define BUF 1024
main(int argc, char *argv[])
{
int in,out,chars;
char buffer[BUF];
if(argc!=3)
{
printf(“Ви помилилися у введенні аргументовп”);

exit(1);
}
if((in=open(argv[1],O_RDONLY))==-1)

{

printf(“Помилка відкриття файлу для копированияп”);

exit(1);
}
if((out=creat(argv[2],755))==-1)
{
printf(“Помилка при створенні нового файлу”);
exit(1);
}
while((chars=read(in,buffer,1024))>0)
write(out,buffer,1024);
}

Зауважу, що новий файл ми створили з правами 755, що означає rwxr-xr-x. Можна було б прийняти ці дані від користувача.
Тепер я розповім про дзвінки такому як: stat.
Він повертає нам інформацію про файл.

Int i=stat(chat *name, struct stat *buff);
chat *name ім'я файлу
struct stat *buff структура типу stat, в ній буде зберігатися інформація про файл.

Які поля є у це структури?:
<
st_mode - тип, права доступу.
st_atime - час останнього доступу.
st_size - розмір.
st_uid - юір юзера.
st_gid - ідентифікатор групи користувачів
st_mtime час останньої модифікації файлу
st_atime час останнього доступу

Для цього виклику потрібно використовувати бібліотеку sys/stat.h
Давайте напишемо приклад, який буде виводити інформацію про заданому файлі:

#include [stdlib.h]
#include [stdio.h]
#include [sys/stat.h]
int main(int ac,char *ag[])
{
struct stat buffer;
int r;
if(ac!=2)
{
printf("будь Ласка введіть необхідні аргументып");
exit(1);
}
if((r=stat(ag[1],&buffer))==-1)
{
printf("Файл не найденп");

exit(1);
}
printf("Розмір файлу: %on",buffer.st_size);
printf("Права доступу до файлу: %dn ",buffer.st_mode);
printf("UID: %dn ",buffer.st_uid);
printf("GID: %dn ",buffer.st_gid);
}Зміна статусної інформації файлу.
Ми вже розібрали кілька операцій з файлами. Тепер давайте поговоримо про зміну інформації про файл. А це ім'я, gid, uid, і т. п.
Взагалі для цих цілей існують спеціальні виклики (розглянемо нижче), але їх використовувати необов'язково.
Наведу приклад, потрібно змінити uid файлу. Для цього використовуємо всю ту структуру stat, але тепер не зчитуємо інформацію, а записуємо її. Приклад.
buffer.st_uid=0644;
А ось такий приклад змінює uid файлу на наш власний.
buffer.st_uid=getuid();
Прокоментую що getuid() повертає юір поточного юзера.

Ось такий приклад перевіряє рут ви чи ні:

If(getuid()!=0)
Printf(Ви не рут, курите далі»)
Else
Printf(«Схоже ви порутили цей сервер =)»);
Вище згадувалося, що існують спеціальні функції для зміни статусної інформації про файл. Розглянемо їх:
Міняємо ім'я файлу
Rename(char *oldname, char *newname);
char *oldname старе ім'я
char *newname нове ім'я
Для використання підключаємо stdio.h
Приклад:
rename(/dvu,/home/stranger/jd);
Міняємо права доступу до файлу.
chmod(char *namefile, mode_t mode);
char *namefile шлях і ім'я файлу
mode_t mode нові права для файлу.
Для испольвания підключаємо sys/types.h, sys/stat.h
Приклад
chmod(/sploit.c,755);
Змінюємо uid,gid:
chown(char *filename,uid_t uid,gid_t gid);
char *filename шлях і іми файлу
uid_t uid нові юір
gid_t gid новий gid
Можна вказати тільки uid або тільки gid.
Для использоания підключаємо unistd.h
Приклад:
chown(/jaga,0,11);
Побайтное зміщення.
Наостанок розглянемо ще одну функцію lseek
вона змінює поточну позицію у файлі

lseek(int d,off_t di,int base);

int d дескриптор файлу
ff_t di, — зміщення у байтах
int base позиція.
Позиції бувають такі:
SEEK_SET від початку файлу
SEEK_CUR - від поточної позиції
SEEK_END від кінця файла
Напишемо приклад, який додає рядок у кінець текстового файлу
#include <[unistd.h]
#include [sys/types.h]
#include [fcntl.h]
#include [stdio.h]
int main()
{
int r;
r=open("/home/stranger/hell.txt",O_RDWR);
lseek(r,0,SEEK_END);
write(r,"hello man!",sizeof("hello man!"));
close®;
}OUTRO
На цьому поки все. Якщо стаття буде актуальна, то продовжу писати.
Як додатковий матеріал можу дати вам статтю Річарда Столлмена Проект GNU
http://www.gnu.org/gnu/thegnuproject.html вихідний текст англійська, але знизу сторінки можна знайти переклад
Удачі!
ps соррі за неграмотне оформлення, у більш красивому вигляді статтю можна побачити тут